< prev index next >

src/java.base/share/classes/sun/invoke/util/Wrapper.java

Print this page
rev 13066 : 8142487: Cleanup sun.invoke.util.Wrapper zeroes to be both reliable and lazy
Reviewed-by: vlivanov, jrose

*** 24,74 **** */ package sun.invoke.util; public enum Wrapper { ! // wrapperType primitiveType char zero emptyArray format ! BOOLEAN( Boolean.class, boolean.class, 'Z', Boolean.FALSE, new boolean[0], Format.unsigned( 1)), // These must be in the order defined for widening primitive conversions in JLS 5.1.2 // Avoid boxing integral types here to defer initialization of internal caches ! BYTE ( Byte.class, byte.class, 'B', new Byte((byte)0), new byte[0], Format.signed( 8)), ! SHORT ( Short.class, short.class, 'S', new Short((short)0), new short[0], Format.signed( 16)), ! CHAR (Character.class, char.class, 'C', new Character((char)0), new char[0], Format.unsigned(16)), ! INT ( Integer.class, int.class, 'I', new Integer(0), new int[0], Format.signed( 32)), ! LONG ( Long.class, long.class, 'J', new Long(0), new long[0], Format.signed( 64)), ! FLOAT ( Float.class, float.class, 'F', (Float)(float)0, new float[0], Format.floating(32)), ! DOUBLE ( Double.class, double.class, 'D', (Double)(double)0, new double[0], Format.floating(64)), ! OBJECT ( Object.class, Object.class, 'L', null, new Object[0], Format.other( 1)), // VOID must be the last type, since it is "assignable" from any other type: ! VOID ( Void.class, void.class, 'V', null, null, Format.other( 0)), ; private final Class<?> wrapperType; private final Class<?> primitiveType; private final char basicTypeChar; - private final Object zero; private final Object emptyArray; private final int format; private final String wrapperSimpleName; private final String primitiveSimpleName; ! private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object zero, Object emptyArray, int format) { this.wrapperType = wtype; this.primitiveType = ptype; this.basicTypeChar = tchar; - this.zero = zero; this.emptyArray = emptyArray; this.format = format; this.wrapperSimpleName = wtype.getSimpleName(); this.primitiveSimpleName = ptype.getSimpleName(); } /** For debugging, give the details of this wrapper. */ public String detailString() { return wrapperSimpleName+ java.util.Arrays.asList(wrapperType, primitiveType, ! basicTypeChar, zero, "0x"+Integer.toHexString(format)); } private abstract static class Format { static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12; --- 24,72 ---- */ package sun.invoke.util; public enum Wrapper { ! // wrapperType primitiveType char emptyArray format ! BOOLEAN( Boolean.class, boolean.class, 'Z', new boolean[0], Format.unsigned( 1)), // These must be in the order defined for widening primitive conversions in JLS 5.1.2 // Avoid boxing integral types here to defer initialization of internal caches ! BYTE ( Byte.class, byte.class, 'B', new byte[0], Format.signed( 8)), ! SHORT ( Short.class, short.class, 'S', new short[0], Format.signed( 16)), ! CHAR (Character.class, char.class, 'C', new char[0], Format.unsigned(16)), ! INT ( Integer.class, int.class, 'I', new int[0], Format.signed( 32)), ! LONG ( Long.class, long.class, 'J', new long[0], Format.signed( 64)), ! FLOAT ( Float.class, float.class, 'F', new float[0], Format.floating(32)), ! DOUBLE ( Double.class, double.class, 'D', new double[0], Format.floating(64)), ! OBJECT ( Object.class, Object.class, 'L', new Object[0], Format.other( 1)), // VOID must be the last type, since it is "assignable" from any other type: ! VOID ( Void.class, void.class, 'V', null, Format.other( 0)), ; private final Class<?> wrapperType; private final Class<?> primitiveType; private final char basicTypeChar; private final Object emptyArray; private final int format; private final String wrapperSimpleName; private final String primitiveSimpleName; ! private Wrapper(Class<?> wtype, Class<?> ptype, char tchar, Object emptyArray, int format) { this.wrapperType = wtype; this.primitiveType = ptype; this.basicTypeChar = tchar; this.emptyArray = emptyArray; this.format = format; this.wrapperSimpleName = wtype.getSimpleName(); this.primitiveSimpleName = ptype.getSimpleName(); } /** For debugging, give the details of this wrapper. */ public String detailString() { return wrapperSimpleName+ java.util.Arrays.asList(wrapperType, primitiveType, ! basicTypeChar, zero(), "0x"+Integer.toHexString(format)); } private abstract static class Format { static final int SLOT_SHIFT = 0, SIZE_SHIFT = 2, KIND_SHIFT = 12;
*** 221,237 **** * The common thread is that this is what is contained * in a default-initialized variable of the given primitive * type. (For void, it is what a reflective method returns * instead of no value at all.) */ ! public Object zero() { return zero; } /** Produce a zero value for the given wrapper type T. * The optional argument must a type compatible with this wrapper. * Equivalent to {@code this.cast(this.zero(), type)}. */ ! public <T> T zero(Class<T> type) { return convert(zero, type); } /** Return the wrapper that wraps values of the given type. * The type may be {@code Object}, meaning the {@code OBJECT} wrapper. * Otherwise, the type must be a primitive. * @throws IllegalArgumentException for unexpected types --- 219,261 ---- * The common thread is that this is what is contained * in a default-initialized variable of the given primitive * type. (For void, it is what a reflective method returns * instead of no value at all.) */ ! public Object zero() { ! switch (this) { ! case BOOLEAN: ! return Boolean.FALSE; ! case INT: ! return (Integer)0; ! case BYTE: ! return (Byte)(byte)0; ! case CHAR: ! return (Character)(char)0; ! case SHORT: ! return (Short)(short)0; ! case LONG: ! return (Long)(long)0; ! case FLOAT: ! return FLOAT_ZERO; ! case DOUBLE: ! return DOUBLE_ZERO; ! case VOID: ! case OBJECT: ! default: ! return null; ! } ! } ! ! private static final Object DOUBLE_ZERO = (Double)(double)0; ! private static final Object FLOAT_ZERO = (Float)(float)0; /** Produce a zero value for the given wrapper type T. * The optional argument must a type compatible with this wrapper. * Equivalent to {@code this.cast(this.zero(), type)}. */ ! public <T> T zero(Class<T> type) { return convert(zero(), type); } /** Return the wrapper that wraps values of the given type. * The type may be {@code Object}, meaning the {@code OBJECT} wrapper. * Otherwise, the type must be a primitive. * @throws IllegalArgumentException for unexpected types
*** 472,482 **** if (source == null || !this.isConvertibleFrom(source)) { throw newClassCastException(wtype, sourceType); } } else if (x == null) { @SuppressWarnings("unchecked") ! T z = (T) zero; return z; } @SuppressWarnings("unchecked") T result = (T) wrap(x); // unchecked warning is expected here assert (result == null ? Void.class : result.getClass()) == wtype; --- 496,506 ---- if (source == null || !this.isConvertibleFrom(source)) { throw newClassCastException(wtype, sourceType); } } else if (x == null) { @SuppressWarnings("unchecked") ! T z = (T) zero(); return z; } @SuppressWarnings("unchecked") T result = (T) wrap(x); // unchecked warning is expected here assert (result == null ? Void.class : result.getClass()) == wtype;
< prev index next >