gpt4 book ai didi

java - 使用 class.forname().newInstance() 实例化类时出错

转载 作者:行者123 更新时间:2023-12-04 06:16:54 25 4
gpt4 key购买 nike

我有许多属于以下结构的类和接口(interface)

interface Parser{}

public class ParserA implements Parser{}
public class ParserB implements Parser{}
public class ParserC implements Parser{}

public abstract class GenericParser implements Parser{}
public abstract class GenericXMLParser extends GenericParser{}

public class ParserD extends GenericXMLParser{}
public class ParserE extends GenericXMLParser{}
public class ParserF extends GenericXMLParser{}

这些类位于不同的包中。这是上述类的包结构。
com.app.parsers.Parser
com.app.parsers.ParserA
com.app.parsers.ParserB
com.app.parsers.ParserC

com.app.parsers.xml.GenericParser
com.app.parsers.xml.GenericXMLParser
com.app.parsers.xml.ParserD
com.app.parsers.xml.ParserE
com.app.parsers.xml.ParserF

我正在尝试使用 class.forname() 创建以下每个类的实例(不确定这种方法的技术名称是什么)
com.app.parsers.ParserA
com.app.parsers.ParserB
com.app.parsers.ParserC
com.app.parsers.xml.ParserD
com.app.parsers.xml.ParserE
com.app.parsers.xml.ParserF

为此,我将所有类名放在一个 vector 中并循环遍历它,如下所示:
    try{
while (tokens.hasMoreTokens())
parsers.addElement(Class.forName((String) tokens.nextToken()).newInstance());
}catch(NullPointerException e){
e.printStackTrace();
}catch(Throwable e){
e.printStackTrace();
}

我遇到的问题是 newInstance() 调用仅适用于前 3 个类,即
com.app.parsers.ParserA
com.app.parsers.ParserB
com.app.parsers.ParserC

当它尝试创建扩展 GenericXMLParser 和 GenericParser 的任何其他类的实例时,我收到以下错误:
com.sun.jdi.InvocationException occurred invoking method.

我遇到的问题是当我运行应用程序时,我没有看到上述错误。我只在调试应用程序时看到它,它发生在 newInstance()
叫做。我不明白是什么原因造成的,因为如果我不在 Debug模式下运行程序,程序运行良好。我也不明白为什么 newInstance() 适用于类
不扩展任何通用类。

另一件事是 InvocationException 没有被上述代码中的 Throwable catch 处理程序捕获,因此很难真正知道是什么原因造成的。这些类都没有任何用户定义的构造函数,所以我真的很想知道是什么原因造成的。

编辑 1

哦,我忘了提到上面正在编译并在 JDK 1.4.1_07 上运行

编辑 2

这是显示调试器上的错误的屏幕截图
enter image description here

编辑 3

@Andrew Young,我必须修改您的示例以使其成为 JDK 1.4.1,因为这是我正在使用的 JDK 版本。我删除了泛型并增强了 for 循环结构,如下所示:
    StringTokenizer tokens = new StringTokenizer(parserList);       

try{
while (tokens.hasMoreTokens()) {
String className = tokens.nextToken();
Class klass = Class.forName(className);
if(!java.lang.reflect.Modifier.isAbstract(klass.getModifiers())) {
java.lang.reflect.Constructor[] constructors = klass.getConstructors();
if(constructors.length > 0) {
boolean foundDefaultConstructor = false;
for(int i = 0; i<constructors.length; i++) {
if(constructors[i].getParameterTypes().length == 0) {
foundDefaultConstructor = true;
break;
}
}
if(foundDefaultConstructor) {
Object parser = klass.newInstance();
parsers.addElement(parser);
} else {
System.err.println("No Default Constructor: " + className);
}
} else {
System.err.println("No Public Constructors: " + className);
}
} else {
System.err.println("Class is abstract: " + className);
}
}

}catch(NullPointerException e){
e.printStackTrace();
}catch(Throwable e){
e.printStackTrace();
}

我尝试运行上面的代码,并且在所有情况下 foundDefaultConstructor 总是设置为 true 并且它继续这个 if block 然后 go 再次循环下一个。
if(foundDefaultConstructor) {
Object parser = klass.newInstance();
parsers.addElement(parser);
}

编辑 4

好的,我试图检查@biziclop 提出的建议
我更改了其中一个解析器并覆盖了它的 toString 方法,它现在只返回一个简单的随机字符串。现在,当在 Eclipse 上调试应用程序时,我没有在 Parser 上看到错误,并使用覆盖的 toString() 方法。听起来这与 toString() 方法有关,但我不确定。

另一件事是,当我在调试器上单击其变量时,解析器现在显示不同

一直工作的总是显示值(value)
ParserA@3fa5ac

那些不工作的显示了值(value)
com.sun.jdi.InvocationException occurred invoking method.

以前没有工作但现在有一个覆盖的 toString() 方法的那个显示了值
"in toString"

以上只是从覆盖的 toString() 方法返回的值。如果它没有显示为 ParserE@3fa5ac 之类的东西,它就可以正确实例化。我还不确定该对象是否是使用覆盖方法实例化的。使用 toString() 方法可能导致这种不同行为的原因是什么。

我现在正在检查现有的解析器,看看它们中是否有任何一个覆盖 toString()。

谢谢
谢谢

最佳答案

仅在调试应用程序时才看到它的原因是 Java 调试接口(interface)引发了此错误。尝试像这样从该行中拉出 nextToken 调用,以查看导致问题的部分:

while (tokens.hasMoreTokens()) {
String className = tokens.nextToken();
Class klass = Class.forName(className);
if(!java.lang.reflect.Modifier.isAbstract(klass.getModifiers())) {
java.lang.reflect.Constructor<?>[] constructors = klass.getConstructors();
if(constructors.length > 0) {
boolean foundDefaultConstructor = false;
for(java.lang.reflect.Constructor<?> constructor: constructors) {
if(constructor.getParameterTypes().length == 0) {
foundDefaultConstructor = true;
break;
}
}
if(foundDefaultConstructor) {
Object parser = klass.newInstance();
parsers.addElement(parser);
} else {
System.err.println("No Default Constructor: " + className);
}
} else {
System.err.println("No Public Constructors: " + className);
}
} else {
System.err.println("Class is abstract: " + className);
}
}

关于java - 使用 class.forname().newInstance() 实例化类时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7125430/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com