1.7 Assigning Values to Variables

Declaring variables, as we did in the last section, simply reserves space in the computer's memory and associates that space with the identifier that we have chosen; it does not give a value to that variable. If we were to write a program that attempted to print the value of a variable after it had been declared but before it had been given a value, Java would give us an error message when we attempted to compile the program.

Once variables are declared, there are many ways in which we can give values to them. One of the simplest ways is to use an assignment statement of the form

<identifier> = <value>;

Although the form of an assignment looks like an equation, it is quite different. The statement causes an action to be performed: the <value> on the right side of the equals sign is stored in the location reserved for the <identifier>. Note that, as with a declaration, an assignment statement is terminated by a semi-colon.

When we first give a value to a variable, we say that we are initializing the variable. Initialization of a variable can be done as soon as it has been declared. In fact, a declaration and assignment can be done in one statement. The next example illustrates this.

Example 1

The statements

 

   int i = 10;
   double x = 2.8, Y = 0.1;
 

will declare the variables i, x, and y and give them values of 10, 2.8, and 0.1 respectively. The results of executing these statements are illustrated in the next diagram.

In any assignment of the form

<identifier> = <value>;

the type of <value> must be compatible with the type of <identifier>. Normally this means that <identifier> and <value> are of identical types but there are some exceptions.

Generally, Java permits conversions from one type to another if it should be safe to make the conversion. For example, Java permits us to assign a byte value to an int variable because any value that can be represented by a byte variable (of 8 bits) can obviously be represented in an int variable (of 32 bits). In Java, such a conversion is referred to as a widening conversion because the new representation is wider (has a greater range) than the old representation. The following table summarizes the valid widening conversions permitted in Java.

Conversions other than the ones listed above can result in the loss of information. Such conversions are called narrowing conversions and should be treated with great care. Because data can be lost in narrowing conversions, the Java compiler complains if you attempt to perform such a conversion, even if the value in the wider representation can safely be stored in the narrower representation.

If you are certain that a narrowing conversion is safe, you can force Java to make the conversion by performing a cast from one type to another. To perform a cast, write the name of the desired type, in parentheses, in front of the value to be converted.

Example 2

The following fragment is valid. It will cause the value 2.5 to be stored in the float variable f.

 

   float f;
   f = (float) 2.5;
 

Java permits the assignment of integer constants to either short or byte variables without using a cast.

 

Example 3

The following statement is valid. It will cause the integer value 75 to be stored in the short variable s.

 

   short s = 75;
 

Here no cast is necessary because the constant integer value being assigned to the short variable is within the permissible range for short values and the compiler can see that the assignment is valid. If we were to write

 

   short s = 75000;
 

the compiler would notice that 75 000 is outside the range of a short variable and it would produce an error message.

A cast is a kind of promise to the compiler that you know what you are doing. If you lie to the compiler, it will trust you and compile the program, but the result may not be correct.

Example 4

The fragment

 

   short s = (short) 75000; 
   System.out.println(s); 
 

will compile and execute without producing an error message. Unfortunately, when it is executed, the value that it prints will be 9464!

If a cast is used to convert a floating point type to an integer type, then any fractional part will be lost.

Example 5

The following fragment will store the value 87 in the int variable i and -32 in j.

 

   int i = (int) 87.65ยท
   int j = (int) -32.999; 

It is also possible to use a cast to convert numerical values to type char. For technical reasons beyond the scope of this book, these are always considered to be narrowing conversions, even conversions from byte to char (where the number of bits is increasing) or from short to char (where the number of bits is unchanged). On the other hand, as noted in the preceding table, a char can be converted to a variety of numerical types. The result of such a conversion is a non-negative integer value - the value of the bit pattern of the character, if this pattern were considered to represent a binary numeral. If you want to gain a better understanding of this, see Appendix C.

Note that the type boolean is not mentioned in the list of widening conversions. This is because variables of type boolean cannot be converted to any of the seven other primitive types. It is also true that none of the other primitive types can be converted to the type boolean.

The right hand sides of assignment statements do not always consist of constant values. An assignment statement can also be used to copy a value from one variable to another.

Example 6

The following fragment will assign the value 1234 to the int variable i and the value 2.71828 to the double variable d. Note that a cast is used to convert the long to an int but no cast is necessary for the widening conversion from float to double.

 

   long 1 = 1234L;
   float f = 2.71828F;
   int i = (int) 1;
   double d = f; 

 

Exercise 1.7

 

  1. Suppose that the following declarations have been made:

 

   int number;

   double mass;

   float density;

   char symbol;

   byte age;

   long limit;

 

State, with reasons, which assignments are illegal.

(a) number = 32.0;

(b) mass = 37;

(c) density = 1.52e0;

(d) symbol = +;

(e) age = 19;

(f) limit = 10000;

 

  1. Which of the following conversions always require a cast?

(a) int to char

(b) byte to int

(c) double to float

(d) float to short

(e) double to long

(f) int to float

 

3.      Write a program fragment that declares the short variable subTotal, then declares the int variable grandTotal, initializing grandTotal to zero, and finally copies the value from grandTotal into subTotal.

 

  1. Find and correct the errors.

(a) short s = 25;

     int i = int(s);

(b) int i = 50;

     short s = i;