Search code examples
javagenericstypecasting-operator

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?


Solution

  • 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.