Использование и создание экземпляра внутреннего класса Java

некоторое время назад я написал небольшую программу просмотра/обработки изображений с 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-file для каждой новой кнопки? так далее...

6 ответов


часто внутренний класс создается в коде, который вызывается только один раз (например, при расширении JPanel и добавить ActionListeners to JButtons в конструкторе). Здесь вы создаете экземпляр внутреннего класса в методе, который вы вызываете несколько раз (если я правильно понимаю ваше описание). Каждый раз, когда вы звоните add(), будет создан новый экземпляр внутреннего класса. Как и в именованных классах, существует только один class, но может быть много экземпляров.


в этом коде:

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

на new ActionListener() {...} construct является анонимным внутренним классом. Он ведет себя так, как если бы он был объявлен отдельно как регулярный внутренний класс. Основное отличие заключается в том, что имя генерируется компилятором автоматически. Это эквивалентно:

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 код, он создает новый экземпляр этого класса.

анонимные внутренние классы имеют несколько других ограничений, которые являются последствиями анонимный. Например, если они объявляют поля, поля доступны только (без использования отражения) из класса.


вы создаете новые анонимные классы для прослушивателей действий пункта меню.

в принципе, ваш код

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

определяет новую реализацию класса для ActionListener


  • main.getScr().updateUI(); не является правильным методом для обновления уже видимых объектов Swing, этот метод выглядит и чувствителен

  • использовать JPanel (Не забудьте переопределить PreferredSize в противном случае возвращает Dimension (0, 0)) С paintComponent,

  • если вы хотите удалить ot, добавьте новый контейнер, содержащий изображение, тогда вам нужно вызвать revalidate() и repaint()


  • использовать JList С изображения вместо JMenuItem

  • добавить ListSelectionListener to JList, затем вы можете переключаться между изображениями


  • если не добавляется какой-либо другой JComponent(s) в Container держит Image, а затем использовать JLabel С Icon / ImageIcon

то, что вы делаете, создает анонимную реализацию интерфейса ActionListener. Каждая анонимная реализация будет иметь свой собственный файл класса (называемый ImageList$1.класс, ImageList$2.класс и так далее).

вы также можете сделать что-то подобное, с аналогичными результатами:

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

menuItem.addActionListener(new MyActionListener());

внутренний класс внутри класса компилируется в "родительский".файл класса. Вы можете иметь несколько внутренних классов внутри класса 1. (в результате 1.файлы классов после компиляции) Каждый "вызов" к innerclass (runtime) создаст объект этого innerclass (такой же, как "классы нормы"). Но это не изменит тебя .файл класса.

поэтому при добавлении 3 кнопок одного типа каждый раз будет создаваться новый объект Tha innerclass. Тот же принцип, что и для кнопки себя.