我该如何创建一个类的数组,但我只知道类的文本名称?

3

我目前正在创建一个库,旨在查看一堆字符串并创建窗口。目前,只需要几行代码和一个巨大的配置文件就可以使用它来创建很多窗口和其他东西。我已经设置好了从一些字符串中读取并加载类,以用作方法参数。这是执行此操作的方法:

    private Class<?> getClass(String classname){
        switch(classname){//Check for some primitive type references, since they don't work in the below area
            case "int":
                return int.class;
            case "double":
                return double.class;
            case "boolean":
                return boolean.class;
            case "long":
                return long.class;
            case "short":
                return short.class;
        }
        Class<?> value = null;
        try{
            value = Config.class.getClassLoader().loadClass(classname);
        }catch(ClassNotFoundException ex){
            Error.error(ErrorLevel.severe, "Could not find class- "+classname, ex, ErrorCatagory.classFinding);//A custom error handling system
        }
        return value;//Return the class found from the name
    }

对于普通类,它能够正常工作。例如,如果我将 java.lang.String 放入其中,它会返回 String 类。如果我放入 javax.swing.JTextField,则会返回正确的类。然而,如果我将 java.lang.String[] 放入其中,即请求一个字符串数组,它会崩溃,如下所示:

    Warning in catagory code- message = Could not find suitable instance for method- Expected JTextComponent but found JTextField!
    Severe error in catagory classFinding
    May 16, 2012 11:02:35 AM ErrorAdapter severeError
    SEVERE: Could not find class- java.lang.String[]
    java.lang.ClassNotFoundException: java.lang.String[]
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        at Config.getClass(Config.java:389)
        at Config.getClasses(Config.java:398)
        at Config.methodCall(Config.java:492)
        at Config.call(Config.java:415)
        at Config.chainCall(Config.java:439)
        at Config.call(Config.java:409)
        at main.action(main.java:122)
        at main$1$5.actionPerformed(main.java:63)
        at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
        at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
        at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
        at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
        at java.awt.Component.processMouseEvent(Component.java:6505)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
        at java.awt.Component.processEvent(Component.java:6270)
        at java.awt.Container.processEvent(Container.java:2229)
        at java.awt.Component.dispatchEventImpl(Component.java:4861)
        at java.awt.Container.dispatchEventImpl(Container.java:2287)
        at java.awt.Component.dispatchEvent(Component.java:4687)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
        at java.awt.Container.dispatchEventImpl(Container.java:2273)
        at java.awt.Window.dispatchEventImpl(Window.java:2713)
        at java.awt.Component.dispatchEvent(Component.java:4687)
        at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
        at java.awt.EventQueue.access$000(EventQueue.java:101)
        at java.awt.EventQueue$3.run(EventQueue.java:666)
        at java.awt.EventQueue$3.run(EventQueue.java:664)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
        at java.awt.EventQueue$4.run(EventQueue.java:680)
        at java.awt.EventQueue$4.run(EventQueue.java:678)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

第一行,也就是以“Warning”开头的那一行是因为它在尝试使用Class.getDeclaredMethod()获取JTextField.class中的getText()方法时喜欢崩溃。其余部分是崩溃报告。

是否有一种方法可以修复此问题并使其与任何类/数组深度配合使用(这样它就可以使用java.lang.String[]、javax.swing.JTextField[][][]和int[][]等,而不需要硬编码)?

另外,顺带一提,是否有更好的方法可以根据字符串获取原始类型的类?

4个回答

3

不是之前,但现在可以了。对于非数组部分它起作用了...我尝试运行数组部分,但它崩溃并显示:java.lang.ClassNotFoundException: [Ljava/lang/String;。我尝试删除字符串中的分号,但它又把同样的错误信息返回给我,这次没有分号。我还尝试了方括号,但结果一样。 - Superinventor
在这里工作过。Java 1.7 构建 4。 - user798182
一旦我更新了,它也可以工作。它不能在构建3中工作,但是在以上版本中可以。 - Superinventor

2

[Ljava.lang.String; 是表示 java.lang.String[] 类的运行时签名。

System.out.println(String[].class.getName());

1
Java中的数组名称表示方式不同。您可以按照以下方式修改方法来处理数组:
private Class<?> getClass(String classname){
    switch(classname){//Check for some primitive type references, since they don't work in the below area
        case "int":
            return int.class;
        case "int[]":
            return int[].class;
        case "double":
            return double.class;
        case "double[]":
            return double[].class;
        case "boolean":
            return boolean.class;
        case "boolean[]":
            return boolean[].class;
        case "long":
            return long.class;
        case "long[]":
            return long[].class;
        case "short":
            return short.class;
        case "short[]":
            return short[].class;
        case "char":
            return char.class;
        case "char[]":
            return char[].class;
    }
    Class<?> value = null;
    int arrayLevel = 0;
    while (classname.endsWith("[]")) {
        classname = classname.substring(0, classname.length()-2);
        arrayLevel++;
    }
    while (arrayLevel-- != 0) {
        className = "[L" + className + ";";
    }
    try{
        value = Config.class.getClassLoader().loadClass(classname);
    }catch(ClassNotFoundException ex){
        Error.error(ErrorLevel.severe, "Could not find class- "+classname, ex, ErrorCatagory.classFinding);//A custom error handling system
    }
    return value;//Return the class found from the name
}

е—Ҝ...жҲ‘жІЎжңүзңӢеҲ°д»»дҪ•дјҡиҝ”еӣһеғҸJTextField[].classиҝҷж ·зҡ„еҖјзҡ„дёңиҘҝпјҢиҝҷжӯЈжҳҜжҲ‘жӯЈеңЁеҜ»жүҫзҡ„пјҲиҝ”еӣһзҡ„еҖјдҪңдёәеҸӮж•°зұ»еһӢзҡ„дёҖйғЁеҲҶиў«дј йҖ’з»ҷClass.getDeclaredMethod()пјүгҖӮйӮЈеҸҜиғҪеңЁе“ӘйҮҢе‘ўпјҹ - Superinventor
@Superinventor 如果它能找到 JTextField,那么检查 endsWith("[]") 的代码应该能够修改类名以匹配Java的期望(即在元素类名前加上 "[L" 并在后面添加 ";")。 - Sergey Kalinichenko
是的,我看到了那部分...问题是当我添加括号时,它只返回JTextField.class。我想要的是,当我添加括号时,它应该返回JTextField[].class,而不是在没有括号时返回,这样当返回值稍后在Class.getDeclaredMethod()中用作参数类型之一时,就可以查找正确的方法。 - Superinventor
@Superinventor 这非常奇怪 - 它不应该这样做。你尝试过调试它来查看是否采用了 classname = "[L"+ 分支吗? - Sergey Kalinichenko
现在我看了一下,我可以看出它实际上会做ptay89上面提到的事情,只是更加灵活。它起作用了。现在我只需要一个for循环就可以使它与堆栈数组(如int[][])兼容。不过这个我可以自己做。 - Superinventor

0
如果你正在创建一个库,请友好地对待你的客户,使用集合类而不是数组。
对于基本类型,你可以始终传递装箱版本(例如:java.lang.Integer)。

除了当我这样做时,它找不到方法...抱歉,我忘记提到返回值的位置。它作为参数类型的一部分传递给Class.getDeclaredMethod(),所以如果该方法需要一个int,那么这种方法并不真正起作用。无论如何,还是谢谢。 - Superinventor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接