handle array and primary types

This commit is contained in:
金戟 2021-03-17 19:26:50 +08:00
parent fe7420c99a
commit af3af6b272
2 changed files with 92 additions and 38 deletions

View File

@ -3,6 +3,7 @@ package com.alibaba.testable.core.tool;
import com.alibaba.testable.core.model.Null; import com.alibaba.testable.core.model.Null;
import com.alibaba.testable.core.util.TypeUtil; import com.alibaba.testable.core.util.TypeUtil;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
@ -13,39 +14,14 @@ import java.lang.reflect.InvocationTargetException;
public class OmniConstructor { public class OmniConstructor {
public static <T> T newInstance(Class<T> clazz) { public static <T> T newInstance(Class<T> clazz) {
return newInstance(clazz, isJavaAgentEnabled(clazz));
}
public static <T> void appendInstance(Object target, Class<T> clazz) {
return;
}
public static <T> void appendInstance(Object target, int count, Class<T> clazz) {
return;
}
private static boolean isJavaAgentEnabled(Class<?> clazz) {
try { try {
clazz.getDeclaredConstructor(Null.class); if (clazz.isPrimitive()) {
} catch (NoSuchMethodException e) { return newPrimitive(clazz);
return false; } else if (clazz.isArray()) {
} return newArray(clazz);
return true; } else {
} return newObject(clazz);
private static <T> T newInstance(Class<T> 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));
}
} }
return (T)ins;
} catch (NoSuchMethodException e) { } catch (NoSuchMethodException e) {
return null; return null;
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
@ -57,4 +33,87 @@ public class OmniConstructor {
} }
} }
public static <T> void appendInstance(Object target, Class<T> clazz) {
appendInstance(target, 1, clazz);
}
public static <T> void appendInstance(Object target, int count, Class<T> clazz) {
return;
}
private static <T> T newObject(Class<T> 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> T newArray(Class<T> clazz) {
return (T)Array.newInstance(clazz.getComponentType(), 0);
}
private static <T> T newPrimitive(Class<T> 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;
}
} }

View File

@ -76,7 +76,7 @@ class OmniAccessorTest {
DemoParent parent = prepareDemoObject(); DemoParent parent = prepareDemoObject();
Object obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc"); Object obj = PrivateAccessor.<String>invokeStatic(OmniAccessor.class, "getByPath", parent, "c{DemoChild}/gc{DemoGrandChild}", "c/gc");
assertTrue(obj instanceof DemoGrandChild); assertTrue(obj instanceof DemoGrandChild);
assertEquals(1, PrivateAccessor.<Integer>get(obj, "i")); assertEquals(0, PrivateAccessor.<Integer>get(obj, "i"));
} }
@Test @Test
@ -87,12 +87,7 @@ class OmniAccessorTest {
} }
private DemoParent prepareDemoObject() { private DemoParent prepareDemoObject() {
DemoParent parent = new DemoParent(); return OmniConstructor.newInstance(DemoParent.class);
DemoChild child = new DemoChild();
DemoGrandChild grandChild = new DemoGrandChild(1);
PrivateAccessor.set(parent, "c", child);
PrivateAccessor.set(child, "gc", grandChild);
return parent;
} }
} }