8

我正在关注一本初学者的 Java 书籍,其中一个项目是从常见的抛出错误中挑选一个错误,并尝试尽你所能来引发错误。

我选择了 InstantiationError 并且知道你不能实例化抽象类或接口。文档说错误通常被编译器捕获,但如果类的定义发生了不兼容的更改,则可以在运行时抛出。

我不知道在程序运行时如何更改类定义,我正在寻找一些关于我应该进一步阅读的提示。谢谢!

4

4 回答 4

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)
于 2013-02-12T19:52:32.367 回答
6

也许当您在运行时使用反射实例化一个抽象类时。

代码示例:

public abstract class MyAbstractClass{
}

public class MyMainClass() {
    public void test(String[] args) {
             this.getClass().getClassLoader().loadClass("MyAbstractClass").getConstructors()[0].newInstance();
    }
}
于 2013-02-12T19:49:46.407 回答
1

查看Reflection API,它提供了一种按名称实例化类的方法。

public void throwError() {
    AbstractType type = this.getClassLoader().newInstance("my.abstract.Type");
} 
于 2013-02-12T19:49:58.180 回答
1

可能导致此类错误的一件简单的事情是,如果您尝试使用错误数量的参数创建对象。假设构造函数接受两个参数,但您的界面设计为用户可以输入 3 个或更多参数。通常,编译器会捕获参数的数量,但如果它是“动态”创建的,那么它将在运行时被捕获

于 2013-02-12T20:09:42.467 回答