Java 101: Foundations

Java 101: Evaluate Java expressions with operators

Learn about simple expressions and operator-based compound expressions

1 2 3 4 Page 4
Page 4 of 4
bipush 65 ; Push 8-bit Unicode value for A, which is sign-extended to 32-bit int, onto stack.
istore_1  ; Pop this 32-bit value into a special int variable.
...
bipush 67 ; Push 8-bit Unicode value for C, which is sign-extended to 32-bit int, onto stack.
iload_1   ; Push 32-bit Unicode value for A onto stack.
isub      ; Subtract 65 (A) from 67 (C). Push 32-bit result onto stack.

The bi in bipush stands for the byte integer type; the i in istore_1, iload_1, and isub stands for the 32-bit integer type. The compiler has converted the expression into an int value. It makes sense to do so because of the close relationship between character literals (really, unsigned Unicode integers) and Java's signed integers.

In addition to the previous widening rules, Java provides a special widening rule for use with String objects (e.g., string literals). When either operand of the string concatenation operator is not a string, that operand is converted to a string before the concatenation operation is performed. For example, when confronted with "X" + 3, the compiler generates code to convert 3 to "3" before performing the concatenation.

Sometimes, you'll need to deliberately narrow a type where information may be lost. For example, you're drawing a mathematical curve with floating-point coordinates (for accuracy). Because the screen's pixels use integer coordinates, you must convert from floating-point to integer before you can plot a pixel. Java lets you narrow a type via a cast operator. Cast operators are available to perform the following primitive-type conversions:

  • Convert from byte integer to character.
  • Convert from short integer to byte integer or character.
  • Convert from character to byte integer or short integer.
  • Convert from integer to byte integer, short integer, or character.
  • Convert from long integer to byte integer, short integer, character, or integer.
  • Convert from floating-point to byte integer, short integer, character, integer, or long integer.
  • Convert from double precision floating-point to byte integer, short integer, character, integer, long integer, or floating-point.

For example, the (float) cast in float circumference = (float) 3.14159 * 10 * 10; is necessary to convert from double precision floating-point to floating-point.

A cast operator isn't always necessary for the above primitive-type conversions. For example, consider conversion from 32-bit integer to 8-bit byte integer. You don't need to supply a cast operation when assigning a 32-bit integer literal that ranges from -128 to 127 to a variable of byte integer type. For example, you could specify byte b = 100; and the compiler wouldn't complain because no information is lost. (This is why I was previously able to specify short x = 0B0011010101110010;, where the binary literal is of 32-bit integer type, without requiring a (short) cast operator, as in short x = (short) 0B0011010101110010;.) However, if you specified int i = 2; byte b = i;, the compiler would complain because i could contain a value outside the valid range of integers that can be assigned to a byte integer variable.

A short application should help to clarify all of this theory. Check out Listing 11's Convert source code.

Listing 11. Convert.java

class Convert
{
   public static void main(String[] args)
   {
      float f = 1000;
      System.out.println("f = " + f);
      long l = 5000;
      System.out.println("l = " + l);
      System.out.println("'C' - 'A' = " + ('C' - 'A'));
      char base = 'A';
      System.out.println("'C' - base = " + ('C' - base));
      int i = (int) 2.5;
      System.out.println(i);
      byte b = 25;
      System.out.println(b);
      b = (byte) 130;
      System.out.println(b);
      i = 2;
      b = (byte) i;
      System.out.println(b);
   }
}

Listing 11 reveals a good way to identify variables when outputting their values (for debugging or another purpose). Simply concatenate a variable (of arbitrary type) to a string label, as in "f = " + f.

Compile Listing 11 (javac Convert.java) and run the application (java Convert). You should observe the following output:

f = 1000.0
l = 5000
'C' - 'A' = 2
'C' - base = 2
2
25
-126
2

In conclusion

Java's support for expressions is extensive and there is a lot of theory to grasp. I encourage you re-read this article while trying out the sample applications and modifying them to reinforce your understanding of expressions. This knowledge will come in handy when you encounter statements in the next article, which wraps up this three-part mini-series on Java's fundamental language features.

1 2 3 4 Page 4
Page 4 of 4