Tak jsem to vyzkoušel. Trefil jsem, že bytecode kvůli tomu měnit nebudou, dál už můj odhad moc dobrý nebyl. Překládá se to z hlediska konzistence chování tím nejšílenějším způsobem, který mě napadl, tedy uloží se to jako proměnná jednoho typu a na druhý typ se castuje v případě potřeby:
public static void main(java.lang.String[]); Code: 0: ldc #2 // String 0 2: new #3 // class java/lang/StringBuilder 5: dup 6: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 9: invokestatic #5 // InterfaceMethod java/util/List.of:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/util/List; 12: astore_1 13: aload_1 14: iconst_0 15: invokeinterface #6, 2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 20: checkcast #7 // class java/io/Serializable 23: astore_2 24: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream; 27: aload_2 28: checkcast #9 // class java/lang/CharSequence 31: iconst_0 32: invokeinterface #10, 2 // InterfaceMethod java/lang/CharSequence.charAt:(I)C 37: invokevirtual #11 // Method java/io/PrintStream.println:(C)V 40: return
Kdybych to měl zpětně přeložit do Javy (bez generik), vypadalo by to asi takto:
public static void main(java.lang.String[] v0){ java.util.List v1 = java.util.List.of("0" , new java.lang.StringBuilder()); java.io.Serializable v2 = (java.io.Serializable)v1.get(0); java.lang.System.out.println(((java.lang.CharSequence)v2).charAt(0)); }
To ovšem vede k novým edge cases: https://gist.github.com/v6ak/794a6f81d5d06349dcc6eb8d741042b7