On 11/18/2015 01:08 AM, Claes Redestad wrote: > On 2015-11-17 22:13, Remi Forax wrote: >> Hi Claes, >> I fail to see how this code will not throw a CCE at runtime >> if (con instanceof Integer || con instanceof Byte || con instanceof >> Short || con instanceof Character) { >> emitIconstInsn((int) con); >> ... >> >> (int)con is translated by the compiler to ((Integer)con).intValue() >> >> you have to write something like that >> (con instanceof Character)? (char)con: ((Number)con).intValue() > > Well, this is embarrassing. I was fooled by my own sanity testing since > javac makes the unboxing+cast work when type is known: > > Character c = 'a'; > System.out.println((int)c); > > but not when going through an Object reference: > > Object o = 'a'; > System.out.println((int)o); > > This works better: > > if (con instanceof Integer) { > emitIconstInsn((int) con); > return; > } > if (con instanceof Byte) { > emitIconstInsn((int)(byte)con); > return; > } > if (con instanceof Short) { > emitIconstInsn((int)(short)con); > return; > } > if (con instanceof Character) { > emitIconstInsn((int)(char)con); > return; > }
By the way, I see there is a cleaner way to implement emitIconstInsn, see java.lang.invoke.TypeConvertingMethodAdapter.iconst: void iconst(final int cst) { if (cst >= -1 && cst <= 5) { mv.visitInsn(Opcodes.ICONST_0 + cst); } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) { mv.visitIntInsn(Opcodes.BIPUSH, cst); } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) { mv.visitIntInsn(Opcodes.SIPUSH, cst); } else { mv.visitLdcInsn(cst); } } http://hg.openjdk.java.net/jdk9/dev/jdk/file/aa9e8b3916ae/src/java.base/share/classes/java/lang/invoke/TypeConvertingMethodAdapter.java#l285 Thanks, -Aleksey