Concepts / Declaring Variables with Explicit Types in Java

Declaring Variables with Explicit Types in Java

A variable declared with var in Java 11 and later has a definite type, taken from its initial value by the compiler.

  • Programming

A Prediction Before the Explanation

Java 11 introduced the var keyword, which lets you declare a local variable without writing its type name. Many learners who meet var for the first time assume it changes Java into a language where one variable can hold a number at one moment and a piece of text at another. That assumption is natural, because languages such as Python let a variable hold whatever value is assigned to it. This article tests that assumption directly, and then explains what the compiler actually does.

What do you think happens?

Suppose you write var rate = 0.05; and then later write rate = "high";. Does this compile in Java 11 or later?

  • Yes, because var lets the variable hold any type

  • No, because rate has a fixed type that was set by its initial value

Reveal answer
Answer:

No, because rate has a fixed type that was set by its initial value

A var declaration gives the variable a definite type taken from the initial value. Here that value is 0.05, so rate is a decimal type, and assigning a String to it is a compile-time error. The keyword changes how the declaration is written, not what kind of variable is created.

What the Compiler Reads

A var declaration gives the variable a type, and that type comes from the value on the right side of the equals sign. The compiler looks at the initial value, determines what type that value has, and assigns that type to the variable. Nothing about the variable is left open for a later decision. The diagram below traces this flow for a single declaration.

var rate = 0.05declaration as written0.05 is a doubletype of the initial valuerate is a doubletype fixed at compile timecompiler reads the initializerthat type is assigned to the variable
How does the type of the right-hand side flow into the variable, so that the compiler fixes the type at the declaration?

The important word is fixed. The type is not a loose label that can drift over time. It is determined when the declaration is compiled. The value stored in the variable can change later, as long as the new value is compatible with the type. The type itself does not change.

Why Reassignment Is Checked Against the Fixed Type

Because the type is fixed at compile time, every later assignment to the variable is checked against that type. An assignment that fits the type compiles. An assignment that does not fit is rejected before the program runs. The code below uses the rate variable from the prediction to show both outcomes.

java
Notes on the code
  • var rate = 0.05 fixes rate as a decimal type taken from 0.05
  • rate = 0.10 compiles because the new value has the same type
  • rate = 3 compiles because the whole number 3 can be stored in a decimal variable
  • rate = "high" is commented out because it would not compile
Output
error: incompatible types: String cannot be converted to double
(the message produced by javac when the commented line is uncommented)
rate = 0.10decimal value into decimalvariablerate = "high"text is not a decimal typerate = 3whole number converts todecimal
Which later assignments to a var variable compile and which fail, given the type the compiler locked in at the declaration?

The rule to apply when predicting a reassignment is simple. Ask whether the new value can be stored in the type the compiler already fixed. If it can, the line compiles. If it cannot, the line fails, even though the variable is declared with var and not with an explicit type name.

Anatomy of a var Declaration

A var declaration has the same parts as any other local variable declaration, except that the type name is replaced by the keyword var. It has the keyword, a name, an equals sign, and an initial value. The annotated strip below labels each part.

varkeyword in place of a typenameratevariable name=assignment0.05initial value that suppliesthe type;ends the statement
What are the parts of a var declaration, and which part supplies the type?

Where var Is Allowed and Where It Is Not

The var form has two firm restrictions. It can only be used for local variables, meaning variables declared inside subroutines, and a variable declared with var must be given an initial value. The table compares the positions discussed in the source material.

PositionIs var allowed?Reason
Local variable inside a methodYesA local variable with an initial value gives the compiler a value to infer from
Loop control variable in a for loopYesThe loop control variable is a local variable, and its declaration follows the same form
Local variable with no initial valueNoThe compiler has no value from which to determine the type
Field of a classNoThe var form is restricted to local variables
Method parameterNoThe var form is restricted to local variables

Positions where var may and may not be used, based on the restrictions in the source material

var in a for Loop

The loop control variable of a for loop is a local variable, so var can be used there. The declaration part of the loop takes the same form as any other var declaration: the keyword, a name, and an initial value, with the type inferred from that value. The rest of the loop header works as before. The two loops below behave the same way, and the second one only removes the explicit type name.

java
Notes on the code
  • The first loop declares its counter with the explicit type int
  • The second loop declares its counter with var, and the initial value 0 fixes the type as int
  • Both counters are fixed in the same way, so the counter cannot be assigned an incompatible type inside either loop

The source notes that for simple values such as a loop counter, the explicit type is short and clear, so var adds little. Its value increases for parameterized types, which appear later in the course. There the type names can be long and complicated, and var keeps the declaration readable while the compiler still checks the type.

Mistakes Learners Make with var

  • Common mistake

    Believing var makes the variable dynamically typed

    What it looks like
    var rate = 0.05; rate = "high";
    Why it fails

    The type is fixed when the declaration is compiled. The keyword changes how the declaration is written, not the kind of variable created.

    Do this instead

    Treat the type of a var variable as if the type name had been written. Check later assignments against the type taken from the initial value.

  • Common mistake

    Omitting the initial value

    What it looks like
    var total;
    Why it fails

    The compiler determines the type from the initial value, and a declaration without one gives it nothing to work from.

    Do this instead

    Supply an initial value, such as var total = 0;, so the type can be determined.

  • Common mistake

    Using var for a field or a method parameter

    What it looks like
    A class field declared as var count = 0;
    Why it fails

    The var form is restricted to local variables, meaning variables declared inside subroutines.

    Do this instead

    Use an explicit type name for fields and method parameters.

  • Common mistake

    Assuming a later assignment is accepted because the value looks similar to the original

Initializers That Leave the Type Undetermined

The compiler can only fix a type when the initial value has one it can read. Some initializers do not give it that information. A bare null, a bare array literal in braces, and a lambda expression all leave the compiler without a type it can take from the value, so a var declaration using one of them is rejected. The explicit type name is the way to declare these variables. This follows from the rule that the type comes from the initial value: when that value does not establish a type, there is nothing for var to use.

java
Notes on the code
  • The bare array literal in the first line does not give the compiler a type to infer, so it is rejected
  • The explicit declaration on the second line names the array type and compiles

Checking Your Understanding

MEDIUM

Given the declaration var count = 10;, decide whether each of these later statements compiles: count = 25; then count = 2.5; then count = "ten";. For each one, state the type the compiler fixed and explain your answer using the rule about where the type comes from.

Hints
  • Start by identifying the type that the initial value 10 gives the variable
  • Ask whether each new value can be stored in that fixed type, and remember that a whole number can be stored in a decimal variable but a decimal cannot be stored in an integer variable
  • Text cannot be stored in a numeric variable at all

Key Takeaways

  • A variable declared with var in Java 11 and later has a definite type, taken from its initial value by the compiler at compile time.
  • var changes how a declaration is written, not what kind of variable is created. The type does not change, so var does not make Java dynamically typed.
  • Each later assignment is checked against the fixed type. Values compatible with that type compile, and incompatible values are rejected before the program runs.
  • var is allowed only for local variables, including the loop control variable of a for loop, and every var declaration must include an initial value.
  • Initializers such as null, a bare array literal, or a lambda do not establish a type, so an explicit type name is needed for those declarations.