Wednesday, November 23, 2011

To calculate length or size, why array is having a ‘length’ property while the list is having a ‘size()’ method?



int[] arrayInt = new int[] {1, 2, 3, 4, 5, 6};

O/P is: -
arrInt.length = 6

array.length is actually a public final member/field of the array, which contains the number of components of the array. It is final because arrays in java are immutable, which means once the array is defined then an array can not be grow or shrink, however the elements within the array can change. So, it means once the size of array is defined it can not be changed, that is why it is final and treated as a property/field/instance variable.

A java array is allocated with a fixed number of element slots. The "length" attribute will tell you how many. That number is immutable for the life of the array. For a resizable equivalent, you need one of the java.util.List classes - where you can use the size() method to find out how many elements are in use.

List<Integer> list = new ArrayList<Integer>(20);
list.add(1);
list.add(2);
list.add(3);

O/P is: -
list.size() = 3

java.util.List is used when you want a datastructure where you can grow/shrink your datastructure easily as per the need. In java.util.List, the field/property is kept private because java.util.List can be grow/shrink as per the need. So, the size is keeps changing on addition/removal of element from the java.util.List. So, it means java.util.List is a mutable object, and that is why the reason size is a method which returns the size of java.util.List, that is, it tells the number of item currently present in the list irrespective of its capacity.

Monday, November 21, 2011

Why Integer 128 == 128 is false? but 127 == 127 is true ?

Still the question is not clear? Let's rephrase it in this way: - 


Why two integer objects with same value are not equal when using auto-boxing? I mean, let say - Integer i1 = 128, and Integer i2 = 128; i1 and i2 are not equal using ‘==’ operator. On the other hand 127 is equals to 127 i.e. 127 == 127 Why?

Below is the snippet of the java program: -

Integer i1 = 127;
Integer i2 = 127;
Integer i3 = 128;
Integer i4 = 128;
       
if (i1 == i2) { // true
        System.out.println("i1 and i2 are equal");
} else {
        System.out.println("i1 and i2 are not equal");
}
 
if (i3 == i4) { // false
        System.out.println("i3 and i4 are equal");
} else {
        System.out.println("i3 and i4 are not equal");
}
 
O/P (Output is): -
        i1 and i2 are equal
        i3 and i4 are not equal
 

Why i3 is not equal to i4?


Instances of "Integer" are not necessarily unique. An Integer instance is an object; you can think of your 'i3' and 'i4' variables as pointers to a chunk of RAM. That chunk of RAM wraps around an 'int' value.


Java 5 implements 'auto-boxing', a syntaxic feature which tries to automatically fill the gap between the 'int' type (the 32-bit signed integer) and the 'Integer' type (the class where every instance contains an 'int' value). 

The key to understanding this is that the JVM uses a process called "boxing" (or "auto-boxing") when converting an int (like 127) to an Integer object. This involves calling the Integer.valueOf(127) method.

The JavaDoc:java.lang.Integer#valueOf(int)says: "Returns a Integer instance representing the specified int value.



When you write this:


  Integer x = 128;


What actually gets compiled is:


  Integer x = Integer.valueOf(128);


Where Integer.valueOf() is a static method which returns an Integer instance containing the provided 'int' value. Integer.valueOf() may return the same instance twice, or not; in practice, the implementation of Integer.valueOf() often caches instances for small integers, e.g. those from -128 to 127. For other values, it performs a simple 'new Integer(val)' and returns that, hence a new instance every time. This is what you observe.

If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values."  


Integer.valueOf(...) caches int values specifically from -128 to 127. It means if the integer value comes in the range of -128 to 127, then a new instance creation is not required, the valueOf() get the existing instance from the cache if the object is already created, that is, the cached object will be returned.

What that means is that the valueOf() method has a cache of Integer objects, and if the primitive being boxed is in that range, the cached object is returned. It just so happens that 127 are in that range, but 128 is not. So i1 and i2 are the same object, while i3 and j4 are not.


When you use '==' on two 'Integer' values, you are comparing the pointers (the "references" in Java terminology). If two pointers are equal then they point to the same instance, wrapping around a unique value. But if two pointers are distinct, it just means that they point to distinct instances, _not_ that those instances contain distinct 'int' values.


Operators are not overloaded in Java (well, at least not to that point). If you want a numerical comparison then you have to get the numbers themselves, not the wrappers:


  Integer a128 = 128;
  Integer b128 = 128;
  if (a128 == b128) {
      /* you have compared the pointers */
  }
  if (a128.intValue() == b128.intValue()) {
      /* you have compared the numerical values */
  }


Auto-boxing blurs the line a bit between class instances and plain integers, but that does not make integers objects in their own right. The point of auto-boxing is to ease the syntaxic use of integers as keys or values in collections (List, Map...).

So, in order to save memory when primitive types are boxed into the wrapper types, the JVM allocates memory and creates a new object. But for some special cases, the JVM reuses the same object, two instances of the following wrapper objects will always be == when their primitive values are the same. 
  • Boolean
  • Byte
  • Character from \u0000 to \u007f (7f is 127 in decimal)
  • Short and Integer from -128 to 127


Conclusion: - This new feature in J2SE 5.0 has both advantanges and disadvantess, it all depends on where and how are we using the feature. It is recommended by SUN to use them only when there is an “impedance mismatch” between reference types and primitives, for example, when you have to put numerical values into a collection. It is not appropriate to use autoboxing and unboxing for scientific computing, or other performance-sensitive numerical code. An Integer is not a substitute for an int; autoboxing and unboxing blur the distinction between primitive types and reference types, but they do not eliminate it.


References: - 
http://www.javabeat.net/articles/31-autoboxing-in-java-50-2.html
- http://www.javakb.com/Uwe/Forum.aspx/java-programmer/50090/Integer-128-Integer-128