answer
will be set to something before it is used. The otherAnswer
variable is not initialized but never used, and the compiler is equally as happy. Remember, the compiler is only concerned if you try to use uninitialized local variables; it doesn't mind the ones you never use.
The onlyOneBranch
variable is initialized only if check
happens to be true
. The compiler knows there is the possibility for check
to be false
, resulting in uninitialized code, and gives a compiler error. You learn more about the if
statement in Chapter 3, “Making Decisions.”
Passing Constructor and Method Parameters
Variables passed to a constructor or method are called constructor parameters or method parameters, respectively. These parameters are like local variables that have been pre-initialized. The rules for initializing constructor and method parameters are the same, so we focus primarily on method parameters.
In the previous example, check
is a method parameter.
public void findAnswer(boolean check) {}
Take a look at the following method checkAnswer()
in the same class:
public void checkAnswer() { boolean value; findAnswer(value); // DOES NOT COMPILE }
The call to findAnswer()
does not compile because it tries to use a variable that is not initialized. While the caller of a method checkAnswer()
needs to be concerned about the variable being initialized, once inside the method findAnswer()
, we can assume the local variable has been initialized to some value.
Defining Instance and Class Variables
Variables that are not local variables are defined either as instance variables or as class variables. An instance variable, often called a field, is a value defined within a specific instance of an object. Let's say we have a Person
class with an instance variable name
of type String
. Each instance of the class would have its own value for name
, such as Elysia
or Sarah
. Two instances could have the same value for name
, but changing the value for one does not modify the other.
On the other hand, a class variable is one that is defined on the class level and shared among all instances of the class. It can even be publicly accessible to classes outside the class and doesn't require an instance to use. In our previous Person
example, a shared class variable could be used to represent the list of people at the zoo today. You can tell a variable is a class variable because it has the keyword static
before it. You learn about this in Chapter 5. For now, just know that a variable is a class variable if it has the static
keyword in its declaration.
Instance and class variables do not require you to initialize them. As soon as you declare these variables, they are given a default value. The compiler doesn't know what value to use and so wants the simplest value it can give the type: null
for an object, zero for the numeric types, and false
for a boolean
. You don't need to know the default value for char
, but in case you are curious, it is '\u0000'
(NUL).
Inferring the Type with var
You have the option of using the keyword var
instead of the type when declaring local variables under certain conditions. To use this feature, you just type var
instead of the primitive or reference type. Here's an example:
public class Zoo { public void whatTypeAmI() { var name = "Hello"; var size = 7; } }
The formal name of this feature is local variable type inference. Let's take that apart. First comes local variable. This means just what it sounds like. You can only use this feature for local variables. The exam may try to trick you with code like this:
public class VarKeyword { var tricky = "Hello"; // DOES NOT COMPILE }
Wait a minute! We just learned the difference between instance and local variables. The variable tricky
is an instance variable. Local variable type inference works with local variables and not instance variables.
Type Inference of var
Now that you understand the local variable part, it is time to go on to what type inference means. The good news is that this also means what it sounds like. When you type var
, you are instructing the compiler to determine the type for you. The compiler looks at the code on the line of the declaration and uses it to infer the type. Take a look at this example:
7: public void reassignment() { 8: var number = 7; 9: number = 4; 10: number = "five"; // DOES NOT COMPILE 11: }
On line 8, the compiler determines that we want an int
variable. On line 9, we have no trouble assigning a different int
to it. On line 10, Java has a problem. We've asked it to assign a String
to an int
variable. This is not allowed. It is equivalent to typing this:
int number = "five";
var
to mean a variable that can take on any type at runtime. In Java, var
is still a specific type defined at compile time. It does not change type at runtime.
For simplicity when discussing var
, we are going to assume a variable declaration statement is completed in a single line. You could insert a line break between the variable name and its initialization value, as in the following example:
7: public void breakingDeclaration() { 8: var silly 9: = 1; 10: }
This example is valid and does compile, but we consider the declaration and initialization of silly
to be happening on the same line.
Examples with var
Let's go through some more scenarios so the exam doesn't trick you on this topic! Do you think the following compiles?
3: public void doesThisCompile(boolean check) { 4: var question; 5: question = 1; 6: var answer; 7: if (check) { 8: answer = 2; 9: } else { 10: answer = 3; 11: } 12: System.out.println(answer); 13: }
The code does not compile. Remember that for local variable type inference, the compiler looks only at the line with the declaration. Since question
and answer
are not assigned values on the lines where they are defined, the compiler does not know what to make of them. For this reason, both lines 4 and 6 do not compile.
You might find that strange since both branches of the if
/else
do assign a value. Alas, it is not on the same line as the declaration, so it does not count for var
. Contrast this behavior with what we saw a short while ago when we discussed branching and initializing a local variable in our findAnswer()
method.
Now we know the initial value used to determine the type needs to be part of the same statement. Can you figure out why these two statements don't compile?
4: public void