/**********************************************************\ | | | hprose | | | | Official WebSite: http://www.hprose.com/ | | http://www.hprose.org/ | | | \**********************************************************/ /**********************************************************\ * * * ConstructorAccessor.java * * * * ConstructorAccessor class for Java. * * * * LastModified: Aug 3, 2016 * * Author: Ma Bingyao <andot@hprose.com> * * * \**********************************************************/ package hprose.io.access; import hprose.common.HproseException; import java.io.ObjectStreamClass; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Comparator; import java.util.concurrent.ConcurrentHashMap; public class ConstructorAccessor { private final static ConcurrentHashMap<Class<?>, Constructor<?>> ctorCache = new ConcurrentHashMap<Class<?>, Constructor<?>>(); private final static ConcurrentHashMap<Constructor<?>, Object[]> argsCache = new ConcurrentHashMap<Constructor<?>, Object[]>(); private final static Long longZero = (long) 0; private final static Object[] nullArgs = new Object[0]; private final static Short shortZero = (short) 0; private final static Double doubleZero = (double) 0; private final static Byte byteZero = (byte) 0; private final static Integer intZero = 0; private final static Float floatZero = (float) 0; private final static Character charZero = (char) 0; private final static Constructor<Object> nullCtor; private final static Method newInstance; static { Constructor<Object> _nullCtor; try { _nullCtor = Object.class.getConstructor((Class<?>[]) null); } catch (Exception e) { _nullCtor = null; } assert(_nullCtor != null); nullCtor = _nullCtor; Method _newInstance; try { _newInstance = ObjectStreamClass.class.getDeclaredMethod("newInstance", new Class[0]); _newInstance.setAccessible(true); } catch (Exception e) { _newInstance = null; } assert(_newInstance != null); newInstance = _newInstance; } private static class ConstructorComparator implements Comparator<Constructor<?>> { public int compare(Constructor<?> o1, Constructor<?> o2) { return o1.getParameterTypes().length - o2.getParameterTypes().length; } } private static Object[] getArgs(Constructor<?> ctor) { Object[] args = argsCache.get(ctor); if (args == null) { Class<?>[] params = ctor.getParameterTypes(); args = new Object[params.length]; for (int i = 0; i < params.length; ++i) { Class<?> type = params[i]; if (int.class.equals(type) || Integer.class.equals(type)) { args[i] = intZero; } else if (long.class.equals(type) || Long.class.equals(type)) { args[i] = longZero; } else if (byte.class.equals(type) || Byte.class.equals(type)) { args[i] = byteZero; } else if (short.class.equals(type) || Short.class.equals(type)) { args[i] = shortZero; } else if (float.class.equals(type) || Float.class.equals(type)) { args[i] = floatZero; } else if (double.class.equals(type) || Double.class.equals(type)) { args[i] = doubleZero; } else if (char.class.equals(type) || Character.class.equals(type)) { args[i] = charZero; } else if (boolean.class.equals(type) || Boolean.class.equals(type)) { args[i] = Boolean.FALSE; } else { args[i] = null; } } argsCache.put(ctor, args); } return args; } @SuppressWarnings({"unchecked"}) public final static <T> T newInstance(Class<T> type) throws HproseException { Constructor<?> ctor = ctorCache.get(type); if (ctor == null) { Constructor<T>[] ctors = (Constructor<T>[]) type.getDeclaredConstructors(); Arrays.sort(ctors, new ConstructorComparator()); for (Constructor<T> c : ctors) { try { c.setAccessible(true); T obj = c.newInstance(getArgs(c)); ctorCache.put(type, c); return obj; } catch (Exception e) {} } ctor = nullCtor; ctorCache.put(type, ctor); } try { if (ctor == nullCtor) { return (T) newInstance.invoke(ObjectStreamClass.lookup(type), nullArgs); } return (T) ctor.newInstance(getArgs(ctor)); } catch (Exception ex) { throw new HproseException(ex.getMessage()); } } }