Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I get ClassCast exception when I enumerate vector with String type parameter, but no exception is there with Integer as type parameter

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?

like image 313
Harshdeep Singh Avatar asked Aug 10 '16 09:08

Harshdeep Singh


1 Answers

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):

  1. System.out.println(String)
  2. System.out.println(Object)

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.

like image 183
Thirler Avatar answered Nov 14 '22 06:11

Thirler