From c9328a340005799201c9d0c1ebfa80570f1d5fb1 Mon Sep 17 00:00:00 2001 From: barreiro Date: Fri, 1 Mar 2013 16:18:53 +0000 Subject: [PATCH] Better support for auto-boxing/unboxing --- .../batoo/common/reflect/FieldAccessor.java | 45 +++++++++++++++--- .../batoo/common/reflect/ReflectHelper.java | 24 +++++++++- .../common/reflect/UnsafeFieldAccessor.java | 46 ++++++++++++++++--- 3 files changed, 100 insertions(+), 15 deletions(-) diff --git a/batoo-common/src/main/java/org/batoo/common/reflect/FieldAccessor.java b/batoo-common/src/main/java/org/batoo/common/reflect/FieldAccessor.java index ed89d99..17e7dac 100644 --- a/batoo-common/src/main/java/org/batoo/common/reflect/FieldAccessor.java +++ b/batoo-common/src/main/java/org/batoo/common/reflect/FieldAccessor.java @@ -23,6 +23,8 @@ import java.security.PrivilegedAction; import org.batoo.common.BatooException; +import org.batoo.common.log.BLogger; +import org.batoo.common.log.BLoggerFactory; /** * Accessor implementation of {@link AbstractAccessor} for the members of {@link Field}s. @@ -32,6 +34,8 @@ */ public class FieldAccessor extends AbstractAccessor { + private static final BLogger LOG = BLoggerFactory.getLogger(FieldAccessor.class); + private enum PrimitiveType { BOOLEAN(Boolean.TYPE), @@ -145,7 +149,8 @@ public void set(Object instance, Object value) { } } else { - switch (this.primitiveType) { + if (value != null) { + switch (this.primitiveType) { case BOOLEAN: if (value instanceof Number) { this.field.set(instance, ((Number) value).byteValue() == 0 ? false : true); @@ -173,13 +178,39 @@ public void set(Object instance, Object value) { this.field.set(instance, ((Number) value).byteValue()); break; default: // CHAR - if (value == null) { - this.field.set(instance, '\u0000'); - } - else { - this.field.set(instance, value); - } + this.field.set(instance, value); break; + } + } + else { // Assign the default values + FieldAccessor.LOG.debug("Primitive field {0} can't be null, using default value instead.", this.field); + + switch (this.primitiveType) { + case BOOLEAN: + this.field.set(instance, false); + break; + case INTEGER: + this.field.set(instance, 0); + break; + case FLOAT: + this.field.set(instance, 0.0f); + break; + case DOUBLE: + this.field.set(instance, 0.0d); + break; + case LONG: + this.field.set(instance, 0l); + break; + case SHORT: + this.field.set(instance, (short) 0); + break; + case BYTE: + this.field.set(instance, (byte) 0); + break; + default: // CHAR + this.field.set(instance, '\u0000'); + break; + } } } } diff --git a/batoo-common/src/main/java/org/batoo/common/reflect/ReflectHelper.java b/batoo-common/src/main/java/org/batoo/common/reflect/ReflectHelper.java index 6f35f80..44e7705 100644 --- a/batoo-common/src/main/java/org/batoo/common/reflect/ReflectHelper.java +++ b/batoo-common/src/main/java/org/batoo/common/reflect/ReflectHelper.java @@ -32,6 +32,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -65,8 +66,29 @@ public class ReflectHelper { static { unsafe = ReflectHelper.getUnSafe(); } - + + private final static Map, Class> wrappersMap = new HashMap, Class>(); + static { + wrappersMap.put(boolean.class, Boolean.class); + wrappersMap.put(byte.class, Byte.class); + wrappersMap.put(short.class, Short.class); + wrappersMap.put(char.class, Character.class); + wrappersMap.put(int.class, Integer.class); + wrappersMap.put(long.class, Long.class); + wrappersMap.put(float.class, Float.class); + wrappersMap.put(double.class, Double.class); + } + private static Class checkAndReturn(Class originalType, Method m, Class actualType) { + if (originalType.isPrimitive()){ + ReflectHelper.LOG.debug("Autoboxing primitive type {0} to test match with return type of method {1}", originalType.getName(), m); + originalType = wrappersMap.get(originalType); + } + if (actualType.isPrimitive()){ + ReflectHelper.LOG.debug("Autoboxing return type of method {0}", m); + actualType = wrappersMap.get(actualType); + } + if (!originalType.isAssignableFrom(actualType)) { ReflectHelper.LOG.warn("Method {0} must return type of {1}", m, originalType.getName()); } diff --git a/batoo-common/src/main/java/org/batoo/common/reflect/UnsafeFieldAccessor.java b/batoo-common/src/main/java/org/batoo/common/reflect/UnsafeFieldAccessor.java index 14fc4e1..ca2844b 100644 --- a/batoo-common/src/main/java/org/batoo/common/reflect/UnsafeFieldAccessor.java +++ b/batoo-common/src/main/java/org/batoo/common/reflect/UnsafeFieldAccessor.java @@ -22,6 +22,9 @@ import java.security.AccessController; import java.security.PrivilegedAction; +import org.batoo.common.log.BLogger; +import org.batoo.common.log.BLoggerFactory; + /** * Accessor implementation of {@link AbstractAccessor} for the members of {@link Field}s. * @@ -30,6 +33,8 @@ */ public class UnsafeFieldAccessor extends AbstractAccessor { + private static final BLogger LOG = BLoggerFactory.getLogger(UnsafeFieldAccessor.class); + private enum PrimitiveType { BOOLEAN(Boolean.TYPE), @@ -165,7 +170,8 @@ public void set(Object instance, Object value) { } } else { - switch (this.primitiveType) { + if (value != null) { + switch (this.primitiveType) { case BOOLEAN: if (value instanceof Number) { ReflectHelper.unsafe.putBoolean(instance, this.fieldOffset, ((Number) value).byteValue() == 0 ? false : true); @@ -193,13 +199,39 @@ public void set(Object instance, Object value) { ReflectHelper.unsafe.putByte(instance, this.fieldOffset, ((Number) value).byteValue()); break; default: // CHAR - if (value == null) { - ReflectHelper.unsafe.putChar(instance, this.fieldOffset, '\u0000'); - } - else { - ReflectHelper.unsafe.putChar(instance, this.fieldOffset, (Character) value); - } + ReflectHelper.unsafe.putChar(instance, this.fieldOffset, (Character) value); + break; + } + } + else { // Assign the default values + UnsafeFieldAccessor.LOG.debug("Primitive field {0} can't be null, using default value instead.", this.field); + + switch (this.primitiveType) { + case BOOLEAN: + ReflectHelper.unsafe.putBoolean(instance, this.fieldOffset, false); + break; + case INTEGER: + ReflectHelper.unsafe.putInt(instance, this.fieldOffset, 0); + break; + case FLOAT: + ReflectHelper.unsafe.putFloat(instance, this.fieldOffset, 0.0f); break; + case DOUBLE: + ReflectHelper.unsafe.putDouble(instance, this.fieldOffset, 0.0d); + break; + case LONG: + ReflectHelper.unsafe.putLong(instance, this.fieldOffset, 0l); + break; + case SHORT: + ReflectHelper.unsafe.putShort(instance, this.fieldOffset, (short) 0); + break; + case BYTE: + ReflectHelper.unsafe.putByte(instance, this.fieldOffset, (byte) 0); + break; + default: // CHAR + ReflectHelper.unsafe.putChar(instance, this.fieldOffset, '\u0000'); + break; + } } } }