Monday, October 27, 2008

Generics Introduction



Generics



The generic feature of the java 5 has created quite a
stir in the java community. It is one of the most controversial
addition in java and caused a revolt among some of the experienced
Java developers. However, this new language addition / feature has
gradually been adopted & has become an essential weapon in the
armory of any Java Developer. Even if you are a newbie, you'll need
only a day or two to grasp this concept.



As with any other technology, the 80:20 principle holds
true. 80% of people using generics will only need 20% of its
capabilities. Although generics is much more than a type safety for
Collections, you'll see generics mainly in Collection related codes
and mainly in the new java.util package API's (look in their
javadocs/source codes)







Before the Java 5


Earlier, there was no
way that let a programmer specify that a given Collection would take
a specified object only. So the Collections at that time were not
'type-safe'.


Example of a
pre-Generic code:





List
myList=new ArrayList();


myList.add("A
cool String Object");


myList.add("OK,
can add more Strings");


myList.add(new
Integer(1)); //Only a Wrapper object could enter into a
collection,no primitive


myList.add(new
Float(2.0f));



......



...


Iterator
iterator=myList.Iterator();


while(iterator.hasNext()){





/* One
could only assume(With crossed fingers) that the Iterator here would
retrieve String(or any other specified class)


*/


String
str=(String)iterator.next();


System.out.println(str); //Will
it compile, & then run correctly ?


//Other
String-specific stuff ...





}


Now
the key point here is that the compiler had to depend upon the
assurance of the programmer (by way of casting) that the 'type' of
the collection was indeed what he claimed to be.


In
other words, there was no way that a pre-generic type could function
automatically like the following in java :



int
i="oops";//Will fail at Compile-Time





This
brought about errors/bugs at runtime thereby seriously reducing the
efficiency of developers & increasing the development time of
nearly all Java SE or EE application that used collections. Also, all
this casting code was annoying to write.





Enter
Java 5 / Java Tiger / Java 5.0 / Java 1.5 and Enter Generics


After
the JDK1.5, newer technologies like Generics, for-Each loop,
autoboxing, annotations, etc came about, making life easier for a
java Developer.


Following
the principles of java, a strong-typed language, the generic code
forces a programmer to create a clean code by enforcing compile time
checking instead of getting a Runtime Exception.


The
language syntax with the introduction of generics got wierdier, but
that's what you'll have to do, Angle brackets everywhere<>





List<String>
genlst=new ArrayList<String>();// A generic ArrayList of TYPE =
String


genlst.add("
Hello ");


genlst.add("
World ");





/*


Printing
the contents of the List using the enhanced for loop,the for-Each
loop


*/


for(String
str:genlst) //Note: no Cast() required


System.out.print(genlst);





Now
try adding the following code:





genlst.add(new
StringBuffer("Ouch"));


genlst.add(5); //Ok
to add a primitive, it'll autobox into a Wrapper Class


genlst.add(new
myClass()); //Adding an object of your class


Upon
compilation, the compiler will happily emit following error messages
for the last 3 add operations:





cannot
find symbol


genlst.add(new
StringBuffer("Ouch"));



^


symbol
: method add(java.lang.StringBuffer)


location:
interface java.util.List<java.lang.String>





cannot
find symbol


genlst.add(5);


...
and so on... for every such error


int
i="oops";//Will fail at Compile-Time"





Generics
with an Iterator


If
you are a big fan of Iterator interface or you need that extra
functionality while iterating over your Collection object, you will
get a compile error if you do not parameterize your iterator.


The
following code will display this








List<String>
listOfStrings = new LinkedList<String>( );






listOfStrings.add("Happy");



listOfStrings.add("Birthday");



listOfStrings.add("To");



listOfStrings.add("You");






for
(Iterator itr = listOfStrings.iterator( ); itr.hasNext( ); ) {






String
s = itr.next( );



System.out.println(s);



}


But
at compilation, the compiler will emit the following error:


incompatible
types


found
: java.lang.Object


required
: java.lang.String






String
s=itr.next( );



^


To
rectify, change the Iterator declaration as:






for
(Iterator
<String>
itr = listOfStrings.iterator( ); itr.hasNext( ); ) {





What-If
you parameterize Only the Iterator?


Then,
the compiler will give the Unchecked/Unsafe operation warnings and
may crash during runtime as the Collection actually is no type-safe.





What
Generics is not


There
are a lot of misconceptions regarding this xml-like syntax thing in
java amongst many programmers section uncovers some hard truths
regarding generics.


Generics
is a compile time checking.Again I will repeat, Generics is ONLY a
compile time checking/safety mechanism. The actual bytecode of a
generic class will have little or no differences with a non-generic
class.


Actually,
the compiler will test the generic code at compile time & remove
the generic syntax & add the casting code int the bytecode
automatically.





Generics
code can sometimes, even lull you into a false sense of security.
This happens typically when using generics with a legacy(old) code.
The bugs (Remember, they are Runtime) in the legacy code wouldn't be
detected at compile time.In order to reduce this disadvantage, the
javac compiler will emit the following:





Note:
<the packageHierarchy>\<Your class name>.java uses






unchecked
or unsafe operations.





Note:
Recompile with -Xlint:unchecked for details.





There
is also no autoboxing & polymorphism with generic types. So the
following will not compile:





List<int>
list=new ArrayList<int>(); //Use Integer instead





List<Object>
list=new ArrayList<Integer>(); //No polymorphism allowed





Although
in Collection type, you are free to use polymorphism, something which
has been displayed in all examples here.









What next ?


Just
like any language addition, generics is poised to be further
enhanced. With the possible introduction of refied generics in Java 7
it might be the right time to arm yourself with the knowledge of
generics.






More Stuff


If
you like this article, please leave a comment here. Possibly in near
future, I'll introduce more generics stuff such as generic methods,
generic classes,Type Wildcards,using annotations with generics,etc.



No comments: