https://stackoverflow.com/questions/70358545/how-does-the-new-java-17-type-pattern-matching-switch-works-under-the-hood public class Switch { public static void main(String args[]) { doit(args); } static void doit(Object o) { System.out.println(switch (o) { case String s -> "String"; case String[] arr -> "String Array"; default -> "Object"; }); } } ****************************************************************************** $ javac --release 20 --enable-preview Switch.java $ javap -c Switch.class Compiled from "Switch.java" public class Switch { public Switch(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: aload_0 1: invokestatic #7 // Method doit:(Ljava/lang/Object;)V 4: return static void doit(java.lang.Object); Code: 0: getstatic #13 // Field java/lang/System.out:Ljava/io/PrintStream; 3: aload_0 4: dup 5: invokestatic #19 // 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 #25, 0 // InvokeDynamic #0:typeSwitch:(Ljava/lang/Object;I)I 19: lookupswitch { // 2 0: 44 1: 54 default: 65 } 44: aload_1 45: checkcast #29 // class java/lang/String 48: astore_3 49: ldc #31 // String String 51: goto 67 54: aload_1 55: checkcast #33 // class "[Ljava/lang/String;" 58: astore 4 60: ldc #35 // String String Array 62: goto 67 65: ldc #37 // String Object 67: invokevirtual #39 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 70: return } ********************************************************************** $ java -Djava.lang.invoke.MethodHandle.TRACE_CALLSITE=true --enable-preview -cp . Switch linkCallSite Switch.doit(Switch.java:6) java.lang.runtime.SwitchBootstraps.typeSwitch(Lookup,String,MethodType,Object[])CallSite/invokeStatic typeSwitch(Object,int)int/BSA=[class java.lang.String, class [Ljava.lang.String;] linkMethod java.lang.invoke.MethodHandle.invokeExact(Lookup,String,MethodType,Object[])CallSite/5 linkMethod => java.lang.invoke.LambdaForm$MH/0x0000000801001000.invokeExact_MT000_LLLLLL_L(Object,Object,Object,Object,Object,Object)Object/invokeStatic + (Lookup,String,MethodType,Object[])CallSite linkMethod java.lang.invoke.MethodHandle.invokeExact(Object)Object/5 linkMethod => java.lang.invoke.Invokers$Holder.invokeExact_MT(Object,Object,Object)Object/invokeStatic + (Object)Object linkCallSite java.base/java.lang.runtime.SwitchBootstraps.typeSwitch(SwitchBootstraps.java:128) java.lang.invoke.LambdaMetafactory.metafactory(Lookup,String,MethodType,MethodType,MethodHandle,MethodType)CallSite/invokeStatic accept()Consumer/BSA=[(Object)void, MethodHandle(Object)void, (Object)void] linkMethod java.lang.invoke.MethodHandle.invokeExact(Lookup,String,MethodType,MethodType,MethodHandle,MethodType)CallSite/5 linkMethod => java.lang.invoke.Invokers$Holder.invokeExact_MT(Object,Object,Object,Object,Object,Object,Object,Object)Object/invokeStatic + (Lookup,String,MethodType,MethodType,MethodHandle,MethodType)CallSite linkMethod java.lang.invoke.MethodHandle.invokeExact()Object/5 linkMethod => java.lang.invoke.Invokers$Holder.invokeExact_MT(Object,Object)Object/invokeStatic + ()Object linkCallSite target class => java.lang.invoke.BoundMethodHandle$Species_L linkCallSite target => ()Consumer : invoke001_L_L=Lambda(a0:L/SpeciesData[L => Species_L])=>{ t1:L=Species_L.argL0(a0:L);t1:L} & BMH=[ 0: ( java.lang.runtime.SwitchBootstraps$$Lambda$1/0x0000000801041558@73d16e93 ) ] linkCallSite linkage => java.lang.invoke.Invokers$Holder.linkToTargetMethod(Object)Object/invokeStatic + MethodHandle()Consumer linkCallSite target class => java.lang.invoke.BoundMethodHandle$Species_LL linkCallSite target => (Object,int)int : invoke002_LLI_I=Lambda(a0:L/SpeciesData[LL => BoundMethodHandle$Species_LL],a1:L,a2:I)=>{ t3:L=BoundMethodHandle$Species_LL.argL1(a0:L); t4:L=BoundMethodHandle$Species_LL.argL0(a0:L); t5:I=MethodHandle.invokeBasic(t4:L,a1:L,a2:I,t3:L);t5:I} & BMH=[ 0: MethodHandle = {(Object,int,Object[])int : DMH.invokeStaticInit001_LLIL_I=Lambda(a0:L,a1:L,a2:I,a3:L)=>{ t4:L=DirectMethodHandle.internalMemberNameEnsureInit(a0:L); t5:I=MethodHandle.linkToStatic(a1:L,a2:I,a3:L,t4:L);t5:I} & DMH.MN=java.lang.runtime.SwitchBootstraps.doTypeSwitch(Object,int,Object[])int/invokeStatic } 1: ( [Ljava.lang.Object;@6d06d69c ) ] linkCallSite linkage => java.lang.invoke.LambdaForm$MH/0x0000000801003800.linkToTargetMethod000_LIL_I(Object,int,Object)int/invokeStatic + MethodHandle(Object,int)int String Array ======== CallSite: java.base/java.lang.runtime.SwitchBootstraps.typeSwitch(SwitchBootstraps.java:128) BSM = java.base/java.lang.runtime.SwitchBootstraps.typeSwitch(SwitchBootstraps.java:128) target class = java.lang.invoke.BoundMethodHandle$Species_L target = ()Consumer : invoke=Lambda(a0:L/SpeciesData[L => Species_L])=>{ t1:L=Species_L.argL0(a0:L);t1:L} & BMH=[