How do I declare a variable?

What does it mean to "declare a variable" or "use a variable"?

The Java language has a standard vocabulary of words, including words like "class", "int", "extends", and punctuation like curly braces, commas, semicolons, parentheses, etc.  When you create a variable, you're (temporarily) adding a new word to Java's vocabulary.  If you were teaching Spanish to a friend, you might at one point say "Here's a new word: ventana.  It's a feminine noun, and it means 'window'."  Similarly, when you teach Java a new word, you have to be very clear that you are giving it a new word, and you have to tell Java what kind of a word it is.  This is all done by typing the name of the type (or class) of the variable, then a space, then the (new) name of the variable. Here are two examples:

        int x
        Person prof

Once this is done correctly, you should be able to use that name later on in the same file and Java will know what you're talking about. Note that once you've already specified the type of the variable, you must not specify it again when you use it. For example,

class Dummy {
    void doSomething (int aParameter) {
        int aLocalVariable;

        aLocalVariable = aParameter; // no problem
        int aLocalVariable = aParameter; // illegal: aLocalVariable is already declared
        aLocalVariable = int aParameter; // illegal: aParameter is already declared
        anotherLocalVariable = aParameter; // illegal: anotherLocalVariable has not been declared yet
        int anotherLocalVariable = aParameter; // no problem
        }
    }

Another way to remember it is that each variable's type must be specified once and only once; its name may appear lots of times.

Parameter, local, and instance variables

There are three kinds of variables in Java: parameters, local variables, and instance variables.  All three of them are declared with exactly the same syntax as above: a type (or class) name, a space, and the new name of the variable.  They differ in where you put all this.

class Dummy {
	String anInstanceVariable;
	int anotherInstanceVariable, andYetAnother;

	void doSomething (String thisIsAParameter, int thisIsAnotherParameter) {
		String heresALocalVariable;
		int hereIsAnotherLocalVariable;
		// Java statements go here, and can use any of these:
		// "this.anInstanceVariable", "this.anotherInstanceVariable",
		// "this.andYetAnother", "thisIsAParameter", "thisIsAnotherParameter",
		// "heresALocalVariable", and "hereIsAnotherLocalVariable" .
		// For example,
		heresALocalVariable = this.anInstanceVariable + thisIsAParameter;
		}

	int doSomethingElse (int thisIsAParameter) {
		double heresALocalVariable;
		String andYetAnother;
		// Java statements here can use any of these:
		// "this.anInstanceVariable", "this.anotherInstanceVariable",
		// "this.andYetAnother", "thisIsAParameter", 
		// "heresALocalVariable", and "andYetAnother" .

	}

The three kinds of variables differ in several interesting ways: where they are visible (aka their "scope"), how long they live, and how they get values.
Visibility/Scope Lifetime How do they get a value?
Instance variable the whole class in which they are declared as long as the class instance exists assignment statement in any method in the class, most often a constructor method.
Parameter the method in whose header they are declared disappear as soon as the method in which they are declared returns matched up automatically with arguments when method is called
Local variable the block in which they are declared (usually a whole method) assignment statement in the method, typically immediately after declaring the variable

Which one should I use?

Parameter variables are usually easy to identify: you need a parameter for each piece of information the method will be given by its caller.

To decide whether to declare a particular variable as an instance or a local variable, ask yourself the following questions:

Is the variable a permanent part of the object?
(For example, the name and age of a Person; the values of name and age can change over time, but the fact that the Person has a name and age doesn't change.) If so, make it an instance variable.
Does the variable's value need to be remembered from one method call to the next?
(That is, does one method set the variable, and another method expect it to still have that value? Or does the same method, the next time it's called, expect the variable to still have that value?) If so, make it an instance variable.
Is the variable used only inside one method?
If so, make it a local variable inside that method.
In general, variables should be declared in the smallest scope possible: in particular, if it doesn't need to be an instance variable, it should be a local variable. (CheckStyle looks for instance variables that are used in only one method; these are usually good candidates for becoming local variables of that method.)

Multiple Variables with the Same Name

There are three rules for multiple variables with the same name.

You cannot declare two variables with the same name and the exact same scope.

For example,

class Foo {
   private int x;
   ...
   private double x;
   }
is illegal because the scope of both x's is the Foo class. (Even if one of the x's were public, or if they had the same type, they would still have the same scope and this would still be illegal).

class Foo {
   public void doSomething (int x, int y, int x) {
      ...
      }
   }
is illegal because both x's are declared as parameters to the method, and are therefore visible throughout the method. (Again, whether they're the same type or not makes no difference.)

class Foo {
   public void doSomething () {
      int x;
      int y;
      double x;
      ...
      }
   }
is illegal because the scope of both x's is the body of the method. Again, whether they're the same type makes no difference; it's still illegal.

A common beginner mistake is to put a variable's type in front of its name every time you use it:

class Foo {
   public void doSomething (int y) {
      int x;
      ...
      int x = y + 3;
      }
   }
As far as Java is concerned, the second int x is declaring a new variable named x in the same scope as the previous variable named x, which is illegal. This student presumably meant
class Foo {
   public void doSomething (int y) {
      int x;
      ...
      x = y + 3;
      }
   }
which would be perfectly legal and reasonable.

Variables with non-overlapping scopes have no interaction at all.

For example,

class Dummy {
	void doSomething (String thisIsAParameter, int thisIsAnotherParameter) {
		String heresALocalVariable;
		...
		}

	int doSomethingElse (int thisIsAParameter) {
		double heresALocalVariable;
		...
		}
	}
Although both methods have a parameter named thisIsAParameter, their scopes don't overlap, so Java doesn't care whether they have the same name: references to thisIsAParameter in each method apply to that method's parameter, and there is no automatic connection between the two. Likewise with the two variables named heresALocalVariable.

If two variables with the same name are in "nested" scopes, the one in the smaller scope "hides" the one in the larger scope. Remember, an instance variable's scope is the whole class; a parameter variable's scope is the method; and a local variable's scope is the block (most often a whole method) in which it was declared.

For example,

class Foo {
   private int x;
   public void doSomething (int x, int y) {
      ...
      x = 7;
      this.x = 8;
      }
   }
is perfectly legal: the scope of one variable x is the whole class, while the other is only visible in the doSomething method. The reference to x inside doSomething is to the parameter x, since its scope is smaller. The reference to this.x, of course, is still to the instance variable.

A common illustration of this fact is the following idiom for constructors:

class Foo {
   private int x;
   public Foo (int x) {
      this.x = x;
      }
   ...
   }
This has the effect of copying the parameter into the instance variable. If you were to do the opposite:
class Foo {
   private int x;
   public Foo (int x) {
      x = this.x;
      }
   ...
   }
the constructor would try to change the parameter to match the instance variable (which still has its default value of 0). It would compile without error, but would do nothing whatsoever.

For an extreme example, consider

class Foo {
   private int x = 4;
   public void doSomething () {
      int x = 3;
      System.out.println(x);
      this.doSomethingElse (12);
      System.out.println(x);
      System.out.println (this.x);
      }
   public void doSomethingElse (int x) {
      System.out.println (x);
      x = 7;
      System.out.println (x);
      System.out.println (this.x);
      }
   }
which has three different variables named x, all with different scopes (one instance variable, one a parameter to doSomething, and one local to doSomethingElse). If you call doSomething(), the program will print out 3, then 12, then 7, then 4, then 3, and finally 4 again. (Be sure you understand why.)

And don't you dare turn in programs that are as confusing as this example!


Last modified: Tue Mar 23 13:32:09 EST 2004
Stephen Bloch / sbloch@adelphi.edu