我正在关注一本初学者的java书籍,其中一个项目是从常常抛出的错误中选择一个错误,并尝试尽你所能来引发错误。
我选择了InstantiationError,并且知道你无法实例化抽象类或接口。文档说错误通常由编译器捕获,但如果类的定义发生不兼容的更改,则可以在运行时抛出错误。
我不知道在程序运行时如何更改类定义,我正在寻找一些关于我应该进一步阅读的提示。 谢谢!
答案 0 :(得分:8)
我不知道在程序运行时如何更改类定义
在运行时无法更改,但在编译后可以更改。
例如,试试这个:
// In Test.java
public class Test {
public static void main(String[] args){
System.out.println(new Foo());
}
}
// In Foo.java
public class Foo {
}
编译:
javac Foo.java Test.java
执行命令
java Test
// Some output like this...
Foo@1d6535bf
现在像这样更改Foo.java
:
// No parameterless constructor any more!
public class Foo {
public Foo(int x) {
}
}
重新编译只是 Foo.java
:
javac Foo.java
重新运行测试:
Exception in thread "main" java.lang.NoSuchMethodError: Foo: method <init>()V
not found
at Test.main(Test.java:3)
这是不是我称之为“常常抛出的错误”。
请注意,这不是InstantiationError
- 但您可以再次更改Foo.java
,以便:
public interface Foo {
}
再次,重新编译Foo.java
,这次你会得到:
Exception in thread "main" java.lang.InstantiationError: Foo
at Test.main(Test.java:3)
答案 1 :(得分:6)
可能在运行时使用反射实例化一个抽象类。
代码示例:
public abstract class MyAbstractClass{
}
public class MyMainClass() {
public void test(String[] args) {
this.getClass().getClassLoader().loadClass("MyAbstractClass").getConstructors()[0].newInstance();
}
}
答案 2 :(得分:1)
查看Reflection API,它提供了一种按名称实例化类的方法。
public void throwError() {
AbstractType type = this.getClassLoader().newInstance("my.abstract.Type");
}
答案 3 :(得分:1)
如果您尝试使用错误数量的参数创建对象,则可能导致此类错误的简单事情。假设构造函数有两个参数,但您的界面设计方式使用户可以输入3个或更多参数。通常,编译器会捕获参数的数量,但如果它是“动态”创建的,那么它将在运行时被捕获