How does the new Java 17 type pattern matching switch works under the hood ? As the feature is fairly new, this question doesn't talk about it.
Reminder: for this code to work under Java 17, you need to enable preview features
public static void test (Object o) {
System.out.println(switch(o){
case Number n -> "number " + n;
case Enum e -> "enum " + e;
case String s -> "string " + s;
default -> "other " + o;
});
}
Disassembled version of the code above using javap -c
:
0: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: dup
5: invokestatic #13 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
8: pop
9: astore_1
10: iconst_0
11: istore_2
12: aload_1
13: iload_2
14: invokedynamic #19, 0 // InvokeDynamic #0:typeSwitch:(Ljava/lang/Object;I)I
19: tableswitch { // 0 to 2
0: 44
1: 58
2: 74
default: 90
}
44: aload_1
45: checkcast #23 // class java/lang/Number
48: astore_3
49: aload_3
50: invokedynamic #25, 0 // InvokeDynamic #1:makeConcatWithConstants:(Ljava/lang/Number;)Ljava/lang/String;
55: goto 96
58: aload_1
59: checkcast #29 // class java/lang/Enum
62: astore 4
64: aload 4
66: invokedynamic #31, 0 // InvokeDynamic #2:makeConcatWithConstants:(Ljava/lang/Enum;)Ljava/lang/String;
71: goto 96
74: aload_1
75: checkcast #34 // class java/lang/String
78: astore 5
80: aload 5
82: invokedynamic #36, 0 // InvokeDynamic #3:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
87: goto 96
90: aload_0
91: invokedynamic #39, 0 // InvokeDynamic #4:makeConcatWithConstants:(Ljava/lang/Object;)Ljava/lang/String;
96: invokevirtual #42 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
99: return
Given this key line:
14: invokedynamic #19, 0 // InvokeDynamic #0:typeSwitch:(Ljava/lang/Object;I)I
It looks like Java converts the object into an int in an auto-generated int typeSwitch (Object, int)
method, of which I can't see the generated code.
The goal of this conversion is then to be able to use a regular switch table over int values.
At first, I thought that hashCode of was used, i.e. object.getClass().hashCode()
, as it is done with switch over String, but in fact Class object's hash code isn't constant over consecutive runs of the JVM. So it's impossible unless the mapping table is rebuilt at every execution, what I doub about.
So, the questions are:
What does this typeSwitch method do ?
Is it smarter than a chain of if instanceof else if instanceof ? Is that possible ?
What's the purpose of the additional int passed ?