Java内部类的使用和实例化

时间:2012-11-16 16:03:26

标签: java swing user-interface inner-classes

前段时间我用Java编写了一个小图像查看器/处理程序,如果你愿意的话,可以使用迷你Photoshop。

我希望有一个下拉菜单,我可以在其中选择我打开的哪一个图像将“放在桌面上”,即。显示和应用的方法。我希望图像的名称是菜单中显示的JMenuItem的名称。我还想在添加新图像时出现一个新按钮。

我想了一段时间并最终制作了这个解决方案,这是一个新类,可以在添加图像时处理新按钮的创建。代码如下:

import java.awt.event.*;
import javax.swing.*;
import java.util.*;


public class ImageList{

    private ArrayList<JMenuItem> list;
    private ImageHandler main;
    private ImageLevel img;

    public ImageList() {}

    public void setHandler(ImageHandler hand) {
        main = hand;
        img = main.getImg1();
    }

    public void add(Buffer addi) {
        final String added = addi.getName();
        JMenuItem uusi = new JMenuItem(added);

        main.getMenu5().add(uusi);
        uusi.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                img.setBuffer(added);
                main.getScr().updateUI();
            }
        });
   }
}

这样可行。对于这个网站,我把原来的芬兰名字翻译成了英文,想知道为什么我最初用芬兰语写这些名字......我很痴迷于命名。

在程序运行时,应该多次调用方法add。

我真正无法理解的是ActionListener接口的内部类实现,即它的编译及其工作原理。

如果我的界面上有两个按钮,我希望它们做不同的事情,我需要两个内部类,每个类有一个,每个类都有自己的ActionListener接口的内部实现。但是在我的代码中有一个类似乎可以完成许多工作,一个编译的.class文件,但最终的结果就好像有很多。

有人可以就此问题教育我吗?这个代码在这里是一个类,新的按钮是它的实例吗?他们是新班吗?每个新按钮应该有一个新的.class文件吗?等...

6 个答案:

答案 0 :(得分:5)

通常,内部类在代码中实例化,该代码仅被调用一次(例如,当您在构造函数中扩展JPanel并将ActionListeners添加到JButton时)。在这里,您可以在多次调用的方法中实例化一个内部类(如果我正确理解您的描述)。每次调用add()时,都会创建一个新的内部类实例。与命名类一样,只有一个类,但可能有很多实例。

答案 1 :(得分:3)

在此代码中:

public void add(Buffer addi) {
    . . .
    uusi.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            img.setBuffer(added);
            main.getScr().updateUI();
        }
    });
}

new ActionListener() {...}构造是一个匿名的内部类。它的行为就像它被单独声明为常规内部类一样。主要区别在于名称由编译器自动生成。它相当于:

private class Anonymous implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        img.setBuffer(added);
        main.getScr().updateUI();
    }
}

public void add(Buffer addi) {
    . . .
    uusi.addActionListener(new Anonymous());
}

每次执行addActionListener代码时,都会创建此类的新实例。

匿名内部类还有一些其他限制因素是匿名的。例如,如果他们声明了字段,则只能从类中访问字段(不使用反射)。

答案 2 :(得分:0)

您正在为菜单项操作侦听器创建新的匿名类。

基本上,你的代码

menuItem.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
      img.setBuffer(added);
      main.getScr().updateUI();
  }
});

为ActionListener

定义一个新的类实现

答案 3 :(得分:0)

  • main.getScr().updateUI();不适合更新已经可见的Swing对象,这种方法看起来很敏感

  • 使用JPanel(不要忘记覆盖PreferredSize,否则返回Dimension (0, 0)paintComponent

  • 如果您要删除,请添加一个包含图片的新容器,然后您必须致电revalidate()repaint()


  • JList与图片而不是JMenuItem

  • 一起使用
  • ListSelectionListener添加到JList,然后您就可以切换图像


  • 如果未将任何其他JComponent添加到Container暂挂Image,则将JLabelIcon / ImageIcon
  • 一起使用

答案 4 :(得分:0)

您正在做的是创建ActionListener接口的匿名实现。每个匿名实现都有自己的类文件(称为ImageList $ 1.class,ImageList $ 2.class等)。

你也可以这样做,结果相似:

class MyActionListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      img.setBuffer(added);
      main.getScr().updateUI();
    }
};

menuItem.addActionListener(new MyActionListener());

答案 5 :(得分:0)

类中的内部类编译为“父”.class文件。 你可以在1个类中拥有多个内部类。 (编译后生成1.class文件) 对内部类(运行时)的每次“调用”都将创建该内部类的对象(与“norma类”相同)。但它确实会改变你的.class文件。

因此,当添加相同类型的3个按钮时,每次都会创建一个新的内部类对象。与按钮本身的原理相同。