Saturday, June 21, 2008

Java Primitives Expert

Puzzle 1
Given the following code:

1. public class Example1 {
2. public static void main(String[] args) {
3. byte b = 1;
4. b = b + 1;
5. System.out.println("b: " + b );
6. }
7. }


What is the result?
The result is: Compilation fails.

Why?
The problem is in the line 4: possible loss of precision.
Decimal literals are implicit integers. So the type of literal 1 is integer. Before b + 1 expression computed, b is implicit converted to integer, and the type of b + 1 expression will be integer too.
We try assign an integer value (b + 1) to a byte variable, and it can be cause loss of precision so the compiler does not compile it.

Solution 1
Replace the line 4 to: b += 1; and auto cast will be work.

Solution 2
We can cast the (b + 1) expression explicit to byte: b = (byte) (b + 1);. We must use the brackets around the b + 1 expression, otherwise we cast just the variable b to byte, not the b + 1 expression.

Puzzle 2
Given the following code:

1. public class Example2 {
2. public static void main(String[] args) {
3. float f = 3.0;
5. System.out.println("f: " + f );
6. }
7. }


What is the result?
The result is: Compilation fails.

Why?
The problem is in the line 3: possible loss of precision.
Floating point literals are implicit double.

Solution 1
Cast explicit the 3.0 to float: f = (float) 3.0;.

Solution 2
Declare the 3.0 literal as float literal: f = 3.0f;

Puzzle 3
Giving the following expression:
( p <= q ) && ( q <= p ) && ( p != q )

Can this expression be true (If yes, when?).
Yes, it can.

How?
The answer is simply, autoboxing:
Declare the variables p and q as the following:

Integer p = new Integer(1000);

Integer q = new Integer(1000);

In this case our expression will be true, because
  • in the ( p <= q ) and ( q <= p ) expression p and q behave as primitive types so the expressions are true (because 1000 = 1000),
  • in the ( p != q ) expression p and q behave as objects, so we compare two object references and this references refer two different object, this expression is true.
  • ( p <= q ) is true, ( q <= p ) is true, ( p != q) is true, so ( p <= q ) && ( q <= p ) && ( p != q ) is true.
Puzzle 4 (my favorite)
Given the following code:

01. public class Example3 {
02. public static void main(String[] args) {
03. Integer i1 = 3;
04. Integer i2 = 3;
05. Integer i3 = 1000;
06. Integer i4 = 1000;
07. System.out.println("i1 == i2: " + (i1==i2) );
08. System.out.println("i3 == i4: " + (i3==i4) );
09. }
10. }


What is the output?
The output is:

i1 == i2: true
i3 == i4: false

Why?
First look the output is surprising.
The lines 3 - 6 are strange, but correct, because the autoboxing is worked.

We know the == operator compare object references. Variable i1 and i2 are object so we wait the i1 == i2 expressions will be false, but it's true!

And to top it all the i3 == i4 expression is false. How is it possible?

The answer is simply: Constant pool. JAVA use this pool (among other things) to store the decimal literals:

boolean:
  • true, false
char:
  • '\u0000' ... '\u007F'
byte:
  • -128...127
short
  • -128...127
int:
  • -128...127
long:
  • -128...127
When we use the new keyword then two, different object is constructed, and the == operator return with false:
  • Integer i1 = new Integer(2); Integer i2 = new Integer(2);
But when we don't use the new keyword, then the JAVA search the literal from Constant pool, and assign it to the references, then no object created:
  • Integer i1 = 2; Integer i2 = 2;
But remember, this works only type and range, given above!

No comments: