NK

Some JAVA Strangeness

Currently I'm sharpening my Java skills for the OCP Java Programmer SE 6 exam (formarly SCJP) and as it turned out preparing for this exam turned out to be a lot of fun!

I wrote some code examples to show some of the peculiarities of Java that made me raise my eyebrows.

Integer wrapper caching

public class A
{
public static void main(String[] args)
{
checkSimilarityInteger(127);
System.out.println("------");
checkSimilarityInteger(128);
}

public static void checkSimilarityInteger(int i)
{
Integer i1 = i;
Integer i2 = i;
if (i1 == i2) {
System.out.println("Integer "+i+" == Integer "+i);
} else {
System.out.println("Integer "+i+" != Integer "+i);
}
if (i1.equals(i2)) {
System.out.println("Integer "+i+" equals Integer "+i);
} else {
System.out.println("Integer "+i+" does NOT equal Integer "+i);
}
}
}

Output:

Integer 127 == Integer 127
Integer 127 equals Integer 127
------
Integer 128 != Integer 128
Integer 128 equals Integer 128

Why: Integers from -128 to 127 are cached so return the same object every time.

Pass by reference?

public class A
{
public static void main(String[] args)
{
Object x = null;
populateString(x);
System.out.println(x);
}

static void populateString(Object x2)
{
x2 = "This is a string";
}
}

Output:

null

Why:

One thing that I found surprising is System.out.print(ln) simply prints null for null references. One thing that might not surprise you, but perhaps should, is x has not been assigned the string This is a string because java does not pass by reference. I remember my Java teacher stressing this point a long time ago but I've never appreciated it really until now.

Null array reference and evaluation

public class A
{
public static void main(String[] args)
{
int i = 1;
try {
getArray()[i = 2]++;
} catch (Exception e) {
}
System.out.println("i = " + i);

int j = 1;
try {
getDoubleArray()[getIntAndFail()][j = 2]++;
} catch (Exception e) {
}
System.out.println("j = " + j);
}

public static int[] getArray()
{
return null;
}

public static int[][] getDoubleArray()
{
return null;
}

public static int getIntAndFail() throws Exception
{
if (true) throw new Exception("I failed");
return 0;
}
}

Output:

i = 2
j = 1

Why:

In the first part of main() the getArray() causes a NullPointerException. This NullPointerException will not be detected until after the other operations within the array reference are evaluated. Hence, the assignment i = 2 will be completed before the NullPointerException is thrown.

In the second part of main() the getDoubleArray() also causes a NullPointerException but before the assignment i = 2 is evaluated another Exception is thrown. This Exception does halt the whole evaluation immediately and prevents i = 2 from being evaluated.

Null array reference and evaluation

"String".replace('g','g') == new String("String").replace('g','g')
"String".replace('g','G') == "StrinG"
"String".replace('g','g') == "String"

Output:

false
false
true

Why:

Java Strings are cached locally within a lookup table (= interning). All strings created in the language syntax "String" are automatically interned, whereas new String("String") are not.

.replace(...) returns a new String object (in fact it has to; strings are immutable).

But if .replace(...) always returns a new String object then why don't all three statements return false?

When replace(...) doesn't have to do anything it returns the original object rather than creating a new one which is why the last statement returns true.

Puzzling.

← Home