Jay
Jay

Reputation: 125

How can a string be casted to an Integer?

    LinkedList<Integer> adjMatrix[] = new LinkedList[10];
    Object[] temp = (Object[]) adjMatrix;
    LinkedList<String> string = new LinkedList<String>();
    string.add("abc");
    temp[3] = string;
    System.out.println(adjMatrix[3].get(0));
    //prints abc

    //====================================================

    LinkedList<String>[] stringList = new LinkedList[10];
    Object[] oa = (Object[]) stringList;
    LinkedList<Integer> listInt = new LinkedList<Integer>();
    listInt.add(new Integer(3));
    oa[1] = listInt;
    System.out.println(stringList[1].get(0));
    // gives ClassCastException java.lang.Integer cannot be cast to java.lang.String

I'm kind of confused what exactly happened in the first case, an integer accepted a string value but it didn't happen in the second case. Any thoughts?

Upvotes: 1

Views: 95

Answers (2)

JB Nizet
JB Nizet

Reputation: 691973

In the first case, you're just printing adjMatrix[3].get(0). The compiler thinks that this expression is an Integer. But the actual type doesn't matter: the generated byte-code is

  37: invokevirtual #8                  // Method java/util/LinkedList.get:(I)Ljava/lang/Object;
  40: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V

So it just passes the object it got from the list to PrintStream.println(Object), which then calls String.value() on this object. The compiler never adds a cast to the byte-code, because it's not necessary.

In the second case, you print stringList[1].get(0)+"", which the compiler thinks it's a concatenation of a String with the empty String. So the generated byte-code is

 101: invokevirtual #8                  // Method java/util/LinkedList.get:(I)Ljava/lang/Object;
 104: checkcast     #14                 // class java/lang/String
 107: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 110: ldc           #16                 // String 
 112: invokevirtual #15                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 115: invokevirtual #17                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
 118: invokevirtual #18                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V

As you see, there is a checkcast instruction here, because the bytecode needs to call StringBuilder.append(String), and the expression thus needs to be cast to a String. Since it's actually an Integer, it throws a ClassCastException.

Upvotes: 6

Andreas
Andreas

Reputation: 159135

The first example create a corrupted array. This is why you get warning when trying to use arrays of generics, because the JVM cannot enforce type safety.

Remember, because of type erasure, LinkedList<Integer> adjMatrix[] is actually a LinkedList adjMatrix[] at runtime, i.e. it can store all object types.

Upvotes: 2

Related Questions