Tuesday, October 28, 2008

Java Generics

Java Generics
The Java Generics started with a trivial example implying a container type. The example below is from that category of examples. It's simple routine creates a LinkedList collection and displays the collection's first element:
1: import java.util.List;
2: import java.util.LinkedList;

3: class GenericsTest {
4: public static void main(String[] args) {
5: List floatList=new LinkedList();
6: floatList.add(new Float(4.5));
7: floatList.add(new Float(1.5));
8: Float nr=(Float)(floatList.iterator().next());
9:
10: System.out.println("First float number: "+nr);
11: }
12: }
This is a correct example--meaning, it will compile and run perfectly and will display the first element of the floatList list. But let’s modify it by replacing the line 9:
9: String str=(String)(floatList.iterator().next());
With this modification, the example code will compile without errors, but will not run correctly. Instead, it throws ajava.lang.ClassCastException exception. The exception is fully covered because you cannot cast a Float to a String!
Now you have a dilemma, because it's obvious that the casts from lines 8 and 9 are annoying. Firstly, you know what types of objects you have stored in the list, so why should you write an explicit cast when accessing the list s elements? Secondly, when you accidentally/intentionally mistake the cast type, why you do not get a compile-time error or at least a warning about this problem? Both questions have the same answer: Because Java Collection classes internally treat elements in the collection as Objects.
This problem is responsible for the birth of the Java Generics core idea, which goed like this: What if a developer could indicate the particular data type to be stored in a list? The practical application of this theoretical concept is to use angle brackets, shown in line 5 in the below example (which is the Java Generics version of the previous code):
1: import java.util.List;
2: import java.util.LinkedList;

3: class GenericsTest {
4: public static void main(String[] args) {
5: List floatList = new LinkedList();
6: floatList.add(new Float(4.5));
7: floatList.add(new Float(1.5));
8: Float nr=floatList.iterator().next();
9:
10: System.out.println("First float number: "+nr);
11: }
12: }
Now, your list is a list of Floats—you have specified this by explicitly placing the indicator at line 5. Thanks to this important modification, you no longer need the explicit cast from line 8; in this case, the List is a generic interface that accepts a type parameter, which, in this example, is Float. In any case, using the cast from line 8 in these conditions is not an error, it's an unjustified action.
Now, modify the example by replacing line 9:
9: String str=(String)(floatList.iterator().next());
The example will no longer compile successfully and a very explicit inconvertible types error will be reported. Cool!

Java Generics and Subtyping
Subtyping is a delicate Generics aspect, which may have a start point in the below example:
1: import java.util.List;
2: import java.util.LinkedList;
3:
4: class GenericsSubtype {
5: public static void main(String[] args) {
6:
7: List<Integer> numbers = new LinkedList<Integer>();
8: List<object> objects = numbers;
9: }
10: }

As you can see, line 7 creates a List of Integer using Java Generics. Looking at line 8, you
an probably extrapolate
the key question of Java Generics subtyping: Is a List of Integer a List of Object? In other words, is a collection of A a collection of B?
Most of the time, the answer is yes—but your compiler will disagree. The compiler knows allowing this code to pass will most likely result in
a List containing elements that are not String, down the road. Furthering this example, you will come across a very important rule—and one
that's worth remembering for future sections: If you have X(sub class or sub interface), a subtype of Y, and a generic type declaration (Z), then Z it
is not a subtype of Z.

Wildcards
Wildcards increase Java Generics' flexibility because they permit bounds on the type
of parameters and save you when you dont have specific knoweledge of a type parameter's value. To demonstrate, suppose you want to create a method that displays the elements of a collection. Without Java Generics, your method might look like following example (thedisplayCollection method).

import java.util.List;
import java.util.LinkedList;
import java.util.Collection;
import java.util.Iterator;
public class TestCollectionWithoutGenerics {
static void displayCollection(Collection collection) {
Iterator iterator = collection.iterator();
for (int i = 0; i <>
System.out.println(iterator.next());
}
}
public static void main(String[] args) {
List floatList = new LinkedList();
floatList.add(new Float(4.5));
List stringList = new LinkedList();
stringList.add(new String("string"));
displayCollection(floatList);
displayCollection(stringList);
}
}

Notice how you call the displayCollection method to display a collection of floats and a collection of strings.
Now, rewrite above example using Java Generics—but without wildcards looks like following.
Listing 1#
import java.util.List;
import java.util.LinkedList;
import java.util.Collection;
import java.util.Iterator;

class TestCollectionWithGenericsWithoutWildcards {
static void displayCollection(Collection<Object> collection) {
for (Object obj : collection)
{ System.out.println(obj); }
}
public static void main(String[] args) {
List<Float> floatList = new LinkedList<Float>();
floatList.add(new Float(4.5));
List<String> stringList = new LinkedList<String>();
stringList.add(new String("string"));
displayCollection(floatList);
displayCollection(stringList);
}
}

Now, you have a serious problem, because above example compiles with errors! Why?! Because Object is not the supertype of all kind of collections
(as you already know from the previous section). This is where wildcards solve the problem.

By using a question mark between angle brackets ("?"), instead of Object type, you provide the real supertype of all kind of collections,
which is Collection<?>. This may sound like a minor change, but it is so important that it deserves showing the entire code again looks like following.

Listing 2#
import java.util.List;
import java.util.LinkedList;
import java.util.Collection;
import java.util.Iterator;

class TestCollectionWithGenericsAndWildcards {

static void displayCollection(Collection<?> collection) {
for (Object obj : collection)
{ System.out.println(obj); }
}
public static void main(String[] args) {
List<Float> floatList = new LinkedList<Float>();
floatList.add(new Float(4.5));
List<String> stringList = new LinkedList<String>();
stringList.add(new String("string"));
displayCollection(floatList);
displayCollection(stringList);
}
}

Note: The Collection<?> formula is known as the collection of unknown and it supports elements of any type.
Now it's time to see how to include bounds in wildcards. First, there are two kinds of bounds:

Upper Bound:
When a wildcard includes an upper bound, the generic type is a subtype of the bounding class.
An upper bound is marked by the extends keyword, as you can see in the below prototype which is one of the ArrayList’s constructors:
public ArrayList(Collection<? extends E> c)

Lower Bound:
When a wildcard includes a lower bound, the generic type is a super-type of the bounding class.
Keep in mind that the super-type relation is reflexive. A lower bound is marked by the super keyword, as you can see in the below prototype,
which is the comparator method of the SortedSet class:
Comparator<? super E> comparator()

For a concrete demonstration, suppose you have the following abstract class:

public abstract class AbstractCar {
public abstract void carInfo();
}

Suppose also that you have the following subclasses:

public class LoganCar extends AbstractCar {
public void carInfo(){
System.out.println("-- Logan Info --");
}
}

public class SanderoCar extends AbstractCar {
public void carInfo(){
System.out.println("-- Sandero Info --");
}
}

Now, imagine that you have a list of AbstractCar objects and you want to display the information about every car.
At first, you'd probably implement something like Listing 2.

Everything seems fine, but a closer look will reveal a big problem with your application.
What happens if you have a collection of LoganCar or SanderoCar, not a collection of AbstractCar?
Obviously, the application will not pass compile-time because of what you learned in a previous section.
To fix this, you can use an upper bound to indicate that the showInfo method can be called with a collection of AbstractCar
and any other subtype of AbstractCar, like LoganCar or SanderoCar. following example shows the application again.

import java.util.List;
import java.util.LinkedList;

public class showCarsInfoWildcard {

public static void showInfo(List<? extends AbstractCar> cars){
for (AbstractCar car : cars)
{ car.carInfo(); }
}

public static void main(String[] args){

LoganCar logan_1 = new LoganCar();
LoganCar logan_2 = new LoganCar();
List<LoganCar> mycars = new LinkedList<LoganCar>();
mycars.add(logan_1);
mycars.add(logan_1);
showInfo(mycars);
}
}

Monday, October 27, 2008

java method ambiguous exception

All about the java method ambiguous exception is bit tricky..
When JVM throws java.lang.Error: Unresolved compilation problem: The method is ambiguous?
This compilation problem occurs while method overloading,
for example:-
we have a class with two overloaded methods like
public static void overloadMeth(Integer i){
//do some stuff
}
public static void overloadMeth(String s){
//do some stuff
}
this is fine, but while you are trying to call this method
overloadMeth(null);
by passing 'null' then the method ambiguous exception will be thrown by JVM,
because if JVM allow us to compile this method call, at runtime JVM cant decide witch method to be invoke either method with String arg i.e overloadMeth(String s) or method withInteger arg i.e overloadMeth(Integer i)
If those two methods arguments are in inheritance hirarchy,
ex:
public static void overloadMeth(Object o){
//do some stuff
}
public static void overloadMeth(String s){
//do some stuff
}
now Object and String are in an inheritance hirarchy, while you invoke method(null) by passing null, the method with String arg will be invoked (last subclass in the hirarchy ll be called).