最近在学习反射,想着利用反射如何创建对象,如果遇到只有有参构造方法的对象时,如果非要创建该如何:
public static <T> T buildObj(Class<T> clazz) {
try {
int modifiers = clazz.getModifiers();
Validate.isTrue(!Modifier.isInterface(modifiers), "不支持接口构造");
Validate.isTrue(!Modifier.isAbstract(modifiers), "不支持抽象类构造");
Validate.isTrue(!Enum.class.isAssignableFrom(clazz), "不支持枚举类型构造");
// 获取所有构造方法
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
// 由构造方法的参数从少至多排序
Arrays.sort(constructors, Comparator.comparing(Constructor::getParameterCount));
// 创建对象
for (Constructor<?> constructor : constructors) {
// 是否是共有的方法
if (Modifier.isPublic(constructor.getModifiers())) {
// 获取构造参数
Parameter[] parameters = constructor.getParameters();
if (parameters.length == 0) {
// 如果参数列表为空,直接调用无参构造方法创建新实例
return (T) constructor.newInstance();
} else {
// 如果参数列表不为空,需要传递相应的参数来创建新实例
Object[] params = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
// 省略了获取参数值的代码
params[i] = getParameterValue(parameters[i]);
}
return (T) constructor.newInstance(params);
}
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
throw new RuntimeException("object construction failed");
}
可以给构造参数一些默认值:
private static Object getParameterValue(Parameter parameter) {
Class<?> type = parameter.getType();
if (type.isPrimitive()) {
if (type.getName().equals(boolean.class.getName())) {
return false;
} else {
return 0;
}
} else {
// 处理非基本数据类型的逻辑
if (type.equals(String.class)) {
return "";
} else if (type.equals(List.class)) {
return new ArrayList<>();
} else if (type.equals(Set.class)) {
return new HashSet<>();
} else if (type.equals(Map.class)) {
return new HashMap<>();
} else if (type.equals(Queue.class)) {
return new LinkedList<>();
} else if (type.equals(Stack.class)) {
return new Stack<>();
} else if (type.equals(TreeMap.class)) {
return new TreeMap<>();
}
}
return null;
}
只是简单学习,其实可以用策略模式:
public interface DefaultValueGetter<T> {
T getDefaultValue(Parameter parameter);
}
然后针对具体的类型给出实现即可,简单学习一下就不实现了。