Java中如何使用反射动态创建类?

问题描述 投票:0回答:1

我有一个控股类,它只有“子类”的成员属性。所有持有类的属性都是相同的子类类型,只是变量名不同。

持有类将收到一个 JSON 对象,其中包含 idNo、一些文本和标识符等属性。该标识符将指向将创建其属性的特定子类。

这里分为三部分

  1. 持有具有子类属性的类
  2. JSON 数组
  3. HashMap 包含子类名称的标识符,例如

哈希映射

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
java reflection
1个回答
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));
    }
    
}

如果您没有很好地理解问题,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.