我很想知道在这种情况下MouseAdapter的范围是什么。
class foo extends JPanel()
{
private JMenu edit = new JMenu();
public foo()
{
this.edit.getItem(0).addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 1) {
edit.getItem(0).setEnabled(true);
}
}
});
}
}
我认为MouseAdapter可以访问变量编辑,因为新声明的MouseAdapter是类 foo 的内部类。但是,它无法找到变量编辑。如果我明确地声明了一个内部类并实现了,例如,MouseAdapter接口或其他什么,它可以从其中检测变量编辑。所以我的问题是新MouseAdpater()的范围是什么有?此外,有没有人知道这方面的好读物?非常感谢你。顺便说一句,我得到的错误是从内部类访问局部变量,需要声明它是最终的
答案 0 :(得分:3)
1)edit.getItem(0)
如果存在则返回JMenuItem
,否则返回IllegalArgumentException
2)this.edit.getItem(0)
,而不是返回成员的类
3)edit.getItem(0).addMouseListener(new MouseAdapter(){
是反作用的,因为JMenu
,JMenuItem
已正确实施MouseEvents
,为了更好的解决方法,您必须查看ButtonModel
4)没有理由scope of the mouse adapter
5)聆听来自JMenu
(不是JMenuItem
)的事件,请查看MenuListener
答案 1 :(得分:3)
要回答您的问题,您需要了解JVM如何使用的基础知识。 当编译包含内部类的类时,生成的字节代码实际上并不将内部类实现为类中的类。
为什么错误:本地变量是从内部类访问的,需要声明它是最终的
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenu;
import javax.swing.JPanel;
public class foo extends JPanel
{
public foo()
{
final JMenu edit = new JMenu();
edit.getItem(0).addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 1) {
edit.getItem(0).setEnabled(true);
}
}
});
}
}
编译此程序时,将创建两个文件,Foo.class和Foo $ 1.class。所以现在你的问题来了,因为Second
类foo$1.class
不知道Variable
类中存在First
edit ie { {1}}。
那么如何解决这个问题呢? foo.class
的作用是什么, 它要求开发人员将外部类的变量声明为final 。
现在这样做了,现在JVM在第二个编译的类文件中悄悄地放置一个名为val $ edit的隐藏变量,这里是从JVM
得到的输出
foo.class的输出
javap
现在,编辑是构造函数的本地,因此输出如上所述。
C:\Mine\JAVA\J2SE\folder>javap foo.class
Compiled from "foo.java"
public class foo extends javax.swing.JPanel {
public foo();
}
C:\Mine\JAVA\J2SE\folder>javap foo$1.class
Compiled from "foo.java"
class foo$1 extends java.awt.event.MouseAdapter {
final javax.swing.JMenu val$edit;
final foo this$0;
foo$1(foo, javax.swing.JMenu);
public void mouseClicked(java.awt.event.MouseEvent);
}
val $ edit被分配了相同的值,该值已被分配给编辑,因为现在编译器知道该值无法更改,因为它已被声明为final,因此它可以正常工作。
现在如果我将 edit Variable
从Variable
更改为Local
该怎么办?现在,类的对象知道有关此变量 edit 的所有内容,如果它已更改。所以改变上述程序同样我们得到:
Instance
在这种情况下,我们不会将其声明并定义为import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenu;
import javax.swing.JPanel;
public class foo extends JPanel
{
JMenu edit = new JMenu();
public foo()
{
edit.getItem(0).addMouseListener(new MouseAdapter(){
@Override
public void mouseClicked(MouseEvent e)
{
if (e.getClickCount() == 1) {
edit.getItem(0).setEnabled(true);
}
}
});
}
}
,因为在这种情况下,因为final
是整个类的本地,Variable
是与Variable
即Object Reference
this
以下是C:\Mine\JAVA\J2SE\folder>javap foo.class
Compiled from "foo.java"
public class foo extends javax.swing.JPanel {
javax.swing.JMenu edit;
public foo();
}
在这种情况下的发送方式,即此$ 0:
Variable
根据我的说法,似乎就像解释一样,这种情况如何运作。
刚才我在互联网上找到关于Mystery of Accessibility in Local Inner Classes的精彩解释,这可能会帮助你以更好的方式了解情况: - )
答案 2 :(得分:1)
您的匿名内部类确实存在于其父对象的范围内,正如您所期望的那样。 范围不是问题。
正如错误消息所示,如果该成员被宣布为最终成员,则匿名内部类只能访问其父级的“编辑”成员。
所以,改变
private JMenu edit = new JMenu();
到
private final JMenu edit = new JMenu();
它应该有用。