我正在关注一本初学者的 Java 书籍,其中一个项目是从常见的抛出错误中挑选一个错误,并尝试尽你所能来引发错误。
我选择了 InstantiationError 并且知道你不能实例化抽象类或接口。文档说错误通常被编译器捕获,但如果类的定义发生了不兼容的更改,则可以在运行时抛出。
我不知道在程序运行时如何更改类定义,我正在寻找一些关于我应该进一步阅读的提示。谢谢!
我正在关注一本初学者的 Java 书籍,其中一个项目是从常见的抛出错误中挑选一个错误,并尝试尽你所能来引发错误。
我选择了 InstantiationError 并且知道你不能实例化抽象类或接口。文档说错误通常被编译器捕获,但如果类的定义发生了不兼容的更改,则可以在运行时抛出。
我不知道在程序运行时如何更改类定义,我正在寻找一些关于我应该进一步阅读的提示。谢谢!
我不知道程序运行时如何更改类定义
它在运行时无法更改,但在编译后可以更改。
例如,试试这个:
// 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)
也许当您在运行时使用反射实例化一个抽象类时。
代码示例:
public abstract class MyAbstractClass{
}
public class MyMainClass() {
public void test(String[] args) {
this.getClass().getClassLoader().loadClass("MyAbstractClass").getConstructors()[0].newInstance();
}
}
查看Reflection API,它提供了一种按名称实例化类的方法。
public void throwError() {
AbstractType type = this.getClassLoader().newInstance("my.abstract.Type");
}
可能导致此类错误的一件简单的事情是,如果您尝试使用错误数量的参数创建对象。假设构造函数接受两个参数,但您的界面设计为用户可以输入 3 个或更多参数。通常,编译器会捕获参数的数量,但如果它是“动态”创建的,那么它将在运行时被捕获