diff --git a/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java b/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java index bd8ee1f..23a58b5 100644 --- a/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java +++ b/testable-core/src/main/java/com/alibaba/testable/core/tool/OmniConstructor.java @@ -3,6 +3,7 @@ package com.alibaba.testable.core.tool; import com.alibaba.testable.core.model.Null; import com.alibaba.testable.core.util.TypeUtil; +import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -13,39 +14,14 @@ import java.lang.reflect.InvocationTargetException; public class OmniConstructor { public static T newInstance(Class clazz) { - return newInstance(clazz, isJavaAgentEnabled(clazz)); - } - - public static void appendInstance(Object target, Class clazz) { - return; - } - - public static void appendInstance(Object target, int count, Class clazz) { - return; - } - - private static boolean isJavaAgentEnabled(Class clazz) { try { - clazz.getDeclaredConstructor(Null.class); - } catch (NoSuchMethodException e) { - return false; - } - return true; - } - - private static T newInstance(Class clazz, boolean withJavaAgent) { - try { - Constructor constructor = withJavaAgent ? - clazz.getDeclaredConstructor(Null.class) : clazz.getDeclaredConstructor(); - constructor.setAccessible(true); - Object ins = withJavaAgent ? constructor.newInstance(new Null()) : constructor.newInstance(); - for (Field f : TypeUtil.getAllFields(clazz)) { - f.setAccessible(true); - if (!f.getType().isPrimitive()) { - f.set(ins, newInstance(f.getType(), withJavaAgent)); - } + if (clazz.isPrimitive()) { + return newPrimitive(clazz); + } else if (clazz.isArray()) { + return newArray(clazz); + } else { + return newObject(clazz); } - return (T)ins; } catch (NoSuchMethodException e) { return null; } catch (IllegalAccessException e) { @@ -57,4 +33,87 @@ public class OmniConstructor { } } + public static void appendInstance(Object target, Class clazz) { + appendInstance(target, 1, clazz); + } + + public static void appendInstance(Object target, int count, Class clazz) { + return; + } + + private static T newObject(Class clazz) + throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { + Constructor constructor = getBestConstructor(clazz); + constructor.setAccessible(true); + Object ins = newInstance(constructor); + for (Field f : TypeUtil.getAllFields(clazz)) { + f.setAccessible(true); + f.set(ins, newInstance(f.getType())); + } + return (T)ins; + } + + private static T newArray(Class clazz) { + return (T)Array.newInstance(clazz.getComponentType(), 0); + } + + private static T newPrimitive(Class clazz) { + if (clazz.equals(int.class)) { + return (T)Integer.valueOf(0); + } else if (clazz.equals(char.class)) { + return (T)Character.valueOf((char)0); + } else if (clazz.equals(short.class)) { + return (T)Short.valueOf((short)0); + } else if (clazz.equals(long.class)) { + return (T)Long.valueOf(0L); + } else if (clazz.equals(double.class)) { + return (T)Double.valueOf(0); + } else if (clazz.equals(float.class)) { + return (T)Float.valueOf(0F); + } else if (clazz.equals(byte.class)) { + return (T)Byte.valueOf((byte)0); + } else if (clazz.equals(boolean.class)) { + return (T)Boolean.valueOf(false); + } + return null; + } + + private static boolean isJavaAgentEnabled(Class clazz) { + try { + clazz.getDeclaredConstructor(Null.class); + } catch (NoSuchMethodException e) { + return false; + } + return true; + } + + private static Object newInstance(Constructor constructor) + throws InstantiationException, IllegalAccessException, InvocationTargetException { + Class[] types = constructor.getParameterTypes(); + if (types.length == 1 && types[0].equals(Null.class)) { + return constructor.newInstance(new Null()); + } else { + Object[] args = new Object[types.length]; + for (int i = 0; i < types.length; i++) { + args[i] = newInstance(types[i]); + } + return constructor.newInstance(args); + } + } + + private static Constructor getBestConstructor(Class clazz) throws NoSuchMethodException { + Constructor bestConstructor = null; + int minimalParametersSize = 999; + for (Constructor constructor : clazz.getDeclaredConstructors()) { + Class[] types = constructor.getParameterTypes(); + if (types.length == 1 && types[0].equals(Null.class)) { + return constructor; + } else if (types.length < minimalParametersSize) { + minimalParametersSize = types.length; + bestConstructor = constructor; + } + } + return bestConstructor; + } + } diff --git a/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java b/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java index 546df63..e4f8e93 100644 --- a/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java +++ b/testable-core/src/test/java/com/alibaba/testable/core/tool/OmniAccessorTest.java @@ -76,7 +76,7 @@ class OmniAccessorTest { DemoParent parent = prepareDemoObject(); Object obj = PrivateAccessor.invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc"); assertTrue(obj instanceof DemoGrandChild); - assertEquals(1, PrivateAccessor.get(obj, "i")); + assertEquals(0, PrivateAccessor.get(obj, "i")); } @Test @@ -87,12 +87,7 @@ class OmniAccessorTest { } private DemoParent prepareDemoObject() { - DemoParent parent = new DemoParent(); - DemoChild child = new DemoChild(); - DemoGrandChild grandChild = new DemoGrandChild(1); - PrivateAccessor.set(parent, "c", child); - PrivateAccessor.set(child, "gc", grandChild); - return parent; + return OmniConstructor.newInstance(DemoParent.class); } }