我有一个控股类,它只有“子类”的成员属性。所有持有类的属性都是相同的子类类型,只是变量名不同。
持有类将收到一个 JSON 对象,其中包含 idNo、一些文本和标识符等属性。该标识符将指向将创建其属性的特定子类。
这里分为三部分
哈希映射
dictionary.put("blue", "two");
dictionary.put("black", "one");
dictionary.put("red", "three");
dictionary.put("green", "four");
JSON 数组类似于
[{
"identifier": "blue",
"invoId": 1,
"questNo": 1,
"seqId": "1a",
"answerText": 1
}, {
"identifier": "red",
"invoId": 1,
"questNo": 2,
"seqId": "2a",
"answerText": 0
}, {
"identifier": "green",
"invoId": 1,
"questNo": 3,
"seqId": "3a",
"answerText": 1
}, {
"identifier": "black",
"invoId": 1,
"questNo": 4,
"seqId": "4a"
}
]
如您所见,JSON 数组有颜色,HashMap 有数字颜色,该数字指定要构造哪个子类。
上课
public class HoldingClass {
private SubClass one;
private SubClass two;
private SubClass three;
private SubClass four;
子类
public class SubClass<T> {
private String identifier;
private String seqId;
private int questNo;
boolean answerText;
private int invoId = 1;
我不明白的部分是如何使用反射,使其指向持有类中的特定子类属性,然后构造特定数组元素信息的该子类。
我尝试了这个方法,但似乎不起作用:
public <T> SubClass constructClass(String className, String identifier, String seqId, int questNo, boolean answerText) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> clazz = Class.forName(className);
Class parameters[] = new Class[]{String.class, Integer.class, Object.class};
Constructor<?> constructor = String.class.getConstructor(parameters);
return (SubClass) constructor.newInstance(parameters);
}
我有这个方法来构造类
public void HoldingClass3(String subclassType, String identifier, String seqId, int questNo, boolean answerText) {
try {
Class<?> clazz = Class.forName(subclassType);
SubClass instance = (SubClass) clazz.getDeclaredConstructor(String.class, String.class, int.class, boolean.class)
.newInstance(identifier, seqId, questNo, answerText);
if ("one".equals(subclassType)) {
one = instance;
} else if ("two".equals(subclassType)) {
two = instance;
} else if ("three".equals(subclassType)) {
three = instance;
} else if ("four".equals(subclassType)) {
four = instance;
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
}
但是,当我调用诸如
之类的方法时holdingClass.HoldingClass3("one", "hello", "hello", 1, true);
我收到此错误
java.lang.ClassNotFoundException: one
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:496)
at java.base/java.lang.Class.forName(Class.java:475)
at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:121)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:391)
at java.base/java.lang.Class.forName(Class.java:382)
at Reflection.HoldingClass.HoldingClass3(HoldingClass.java:43)
at com.Nicolaus.Spring.Fundamentals.SpringFundamentalsApplication.main(SpringFundamentalsApplication.java:41)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:578)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50)
Process finished with exit code 0
我认为你不需要为此反思...... 看看这个 JUnit 测试:
持有类别:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class HoldingClass {
private SubClass one;
private SubClass two;
private SubClass three;
private SubClass four;
}
子类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SubClass {
private String identifier;
private String seqId;
private int questNo;
boolean answerText;
private int invoId = 1;
}
测试类:
package com.paulmarcelinbejan.stackoverflow;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
public class StackOverflow {
Map<String, String> dictionary = new HashMap<>();
List<SubClass> subClasses;
Map<String, BiConsumer<HoldingClass, SubClass>> actions = new HashMap<>();
@BeforeEach
void setUp() throws IOException {
actions.put("one", (holdingClass, subClass) -> holdingClass.setOne(subClass));
actions.put("two", (holdingClass, subClass) -> holdingClass.setTwo(subClass));
actions.put("three", (holdingClass, subClass) -> holdingClass.setThree(subClass));
actions.put("four", (holdingClass, subClass) -> holdingClass.setFour(subClass));
dictionary.put("blue", "two");
dictionary.put("black", "one");
dictionary.put("red", "three");
dictionary.put("green", "four");
subClasses = readListFromFile(JSON_FILE, SubClass.class);
}
@Test
void testHowToUseReflectionInJavaToDynamicallyCreateClasses() {
HoldingClass holdingClass = new HoldingClass();
for(SubClass subClass : subClasses) {
String dictionaryValue = dictionary.get(subClass.getIdentifier());
actions.get(dictionaryValue).accept(holdingClass, subClass);
}
assertNotNull(holdingClass.getOne());
assertNotNull(holdingClass.getTwo());
assertNotNull(holdingClass.getThree());
assertNotNull(holdingClass.getFour());
}
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private static final File JSON_FILE = new File("src/test/resources/SubClasses.json");
private static <R> List<R> readListFromFile(final File file, final Class<R> contentClass) throws IOException {
return OBJECT_MAPPER.readValue(file, OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, contentClass));
}
}
如果您没有很好地理解问题,请告诉我。