You are telling the compiler that you want to call Object[].toString(). That's why the compiler generates a cast (checkcast):
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: new #4 // class java/lang/Object
12: dup
13: invokespecial #1 // Method java/lang/Object."<init>":()V
16: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
21: pop
22: aload_1
23: astore_2
24: aload_2
25: iconst_0
26: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: checkcast #7 // class "[Ljava/lang/Object;"
34: invokevirtual #8 // Method java/lang/Object.toString:()Ljava/lang/String;
37: pop
38: return
You can prevent the bytecode cast by adding a cast yourself in the Java code:
public static void main(String[] args) {
List a = new ArrayList();
a.add(new Object());
List<Object[]> b = a;
((Object) b.get(0)).toString();
}
Now the compiler sees that a cast to Object[] is not needed since you only want an Object reference. The checkcast opcode is omitted:
0: new #2 // class java/util/ArrayList
3: dup
4: invokespecial #3 // Method java/util/ArrayList."<init>":()V
7: astore_1
8: aload_1
9: new #4 // class java/lang/Object
12: dup
13: invokespecial #1 // Method java/lang/Object."<init>":()V
16: invokeinterface #5, 2 // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
21: pop
22: aload_1
23: astore_2
24: aload_2
25: iconst_0
26: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
31: invokevirtual #7 // Method java/lang/Object.toString:()Ljava/lang/String;
34: pop
35: return
acontainsObject, and notObject[].Object[] instanceof Objectistrue, no reason for compilation error.