< 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 >