访问最终的局部变量时,为什么在Java中有此InstantiationException?

问题描述:

我正在玩一些代码来制作类似于"closure like"的代码.构造(顺便说一句不起作用)

I was playing with some code to make a "closure like" construct ( not working btw )

一切都很好,但是当我尝试访问代码中的最终局部变量时,抛出了异常InstantiationException.

Everything looked fine but when I tried to access a final local variable in the code, the exception InstantiationException is thrown.

如果我通过完全删除或通过将其设置为class属性来删除对局部变量的访问,则不会发生异常.

If I remove the access to the local variable either by removing it altogether or by making it class attribute instead, no exception happens.

文档说: InstantiationException

当应用程序尝试使用Class类中的newInstance方法创建类的实例时抛出,但无法实例化指定的类对象.实例化失败的原因有多种,包括但不限于:

-类对象表示抽象类,接口,数组类,原始类型或void

-该类没有无效的构造函数

还有什么其他原因可能导致此问题?

What other reason could have caused this problem?

这是代码.注释/取消注释类属性/局部变量以查看效果(第5和10行).

Here's the code. comment/uncomment the class attribute / local variable to see the effect (lines:5 and 10 ).

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
class InstantiationExceptionDemo {
     //static JTextField field = new JTextField();// works if uncommented

    public static void main( String [] args ) {
        JFrame frame = new JFrame();
        JButton button = new JButton("Click");
        final JTextField field = new JTextField();// fails if uncommented

        button.addActionListener( new _(){{
            System.out.println("click " + field.getText());
        }});
    
        frame.add( field );
        frame.add( button, BorderLayout.SOUTH );
        frame.pack();frame.setVisible( true );
    
    }
}
class _ implements ActionListener {
    public void actionPerformed( ActionEvent e ){
        try {
            this.getClass().newInstance();
        } catch( InstantiationException ie ){
            throw new RuntimeException( ie );
        } catch( IllegalAccessException ie ){
            throw new RuntimeException( ie );
        }
    }
}

这是Java中的错误吗?

Is this a bug in Java?

修改

哦,我忘了,stacktrace(抛出时)是:

Oh, I forgot, the stacktrace ( when thrown ) is:

Caused by: java.lang.InstantiationException: InstantiationExceptionDemo$1
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at _.actionPerformed(InstantiationExceptionDemo.java:25)

嗯,这很有意义.

只有您的_类的第一个实例可以访问局部变量.后续实例不能,除非您通过构造函数arg为它们提供实例

Only your first instance of the _ class has access to the local variable. Subsequent instances can't, unless you provide them with it (via constructor arg)

Constructor[] constructor = a.getClass().getDeclaredConstructors();
for (Constructor c : constructors) {
     System.out.println(c.getParameterTypes().length);
}

输出1.(a是您的匿名类的实例)

outputs 1. (a is the instance of your anonymous class)

也就是说,我认为这不是实现闭包的好方法.不需要调用初始化程序块至少一次.我假设您只是在玩耍,但请查看 lambdaj .或等待Java 7:)

That said, I don't think this is a good way to implement closures. The initializer block is called at least once, without the need of it. I assume you are just playing around, but take a look at lambdaj. Or wait for Java 7 :)