I was trying my hands on vectors and wrote a simple code to access its elements through enumeration.
Vector v = new Vector();
v.add("Some String");
v.add(10);
Enumeration e = v.elements();
while(e.hasMoreElements()) System.out.println(e.nextElement());
Working with raw types produces results as expected(prints the elements). But, when I use generic type of enumerator, it gets tricky.
With String as type parameter:
Vector v = new Vector();
v.add("Some String");
v.add(10);
Enumeration<String> e = v.elements();
while(e.hasMoreElements()) System.out.println(e.nextElement());
Output:
Some String
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
With Integer as type parameter:
Vector v = new Vector();
v.add("Some String");
v.add(10);
Enumeration<Integer> e = v.elements();
while(e.hasMoreElements()) System.out.println(e.nextElement());
Output:
Some String
10
What is happening here? Shouldn't both the cases produce ClassCast exception?
Note that all generics are erased at compilation, it is just to help the compiler confirm you have made no mistakes. Probably you get several warnings at this points, saying you should not use raw types (raw means Vector
instead of Vector<String>
etc). The generics equivalent of a raw type is <?>
indicating you will allow any type (note that that will cause you code not to compiler anymore).
The behavior you see is because there are two (actually several more, but in your case two are used) functions with the name System.out.println()
and different parameter types, this is called (method overloading):
At compile time it is decided which is called for your code.
In the String example the enumeration has generic type String
and will call the first. However when it gets passed an Integer
object from your Vector
, this cause a failure when casting to it to String.
So in this case, the compiler converts your code into the following (roughly):
Enumeration e = v.elements();
while(e.hasMoreElements()) System.out.println((String)e.nextElement());
In the Integer example the enumeration has generic type Integer
which will map to System.out.println(Object)
, which accepts both String
and Integer
, so all goes well.
On a sidenote: by default you should use ArrayList
instead of Vector
, it has a much cleaner interface, due to legacy methods in Vector
. Also Vector
it is synchronized causing unneeded overhead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With