Monday, June 20, 2011

Java Pitfall

Recently, I've been interested in some differences between C# and Java. Mainly in how some behaviours are implemented. Consider flowing code:


Byte bigByte = 13;
test(bigByte);

byte smallByte = 14;
test(smallByte);


public void test(Byte b){
System.out.println("byte");
System.out.println(b);
}

public void test(int b){
System.out.println("int");
System.out.println(b);
}



The output is:

byte
13
int
14


I did not expect it. In Java there are mechanisms called widening and autoboxing. Starting from Java 5.0 framework first tries to wide the size of a type that is reserved for it in a memory - in this case Byte is equal to 4 bits, but int reserves 8 bits in a memory. And because before Java 5.0 there was no autoboxing, the framework is trying to find a method that somehow matches the call. Maybe it should throw an error, but designers decided differently. And starting from Java 5.0 the framework is trying to find a method that as an argument also takes a type of a primitive value in this case it is trying to find a type Byte for a byte call.

I understand designers that added autboxing feature, and were trying to keep compatibility with older versions - in a behaviour - this is why Java 5.0 first tries to use widening mechanism and then autoboxing. What concerns me is that the code behaves unnaturally for a person without a knowledge about Java history (when what mechanism was added). In other words, because this code compiles, my first impression is that the method that takes as an argument Byte should be called when I send a message with a byte parameter, but the framework behaves differently.

No comments: