Встретил вот такой интересный участок кода, но ничего не могу про него найти:
JPanel contentPane = new JPanel() {
BufferedImage [] img = new BufferedImage[] { // вот это поле
ImageIO.read(new File("image/_1.png")),
ImageIO.read(new File("image/_2.png"))
};
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img[0],0,0,null);
}
};
Почему после конструкции new JPanel() внутри фигурных скобок присутствуют переменные? Как это называется?
То, с чем мы здесь имеем дело -- это не анонимные поля, это описание анонимного класса, который является потомком класса JPanel
. То, что следует за вызовом конструктора new JPanel()
в фигурных скобках -- это фактически описание нового класса; вы его описываете и сразу же создаете экземпляр этого нового класса и присваиваете его переменной contentPane
типа JPanel
(это возможно, поскольку новый клаcc - дочерний по отношению к JPanel), но вы не можете создавать переменные нового типа, поскольку у нового класса нет своего имени.
Как и любой дочерний класс, новый класс (хоть анонимный, хоть нет) может содержать дополнительные поля и методы, может также переопределять методы родительского класса. Как и при описании любого класса, переменные могут быть инициализированы выражениями, которые вычисляются в момент создания экземпляра класса. Выражения могут содержать вызовы методов, эти методы будут вызываться в момент инициализации. Ваш код
BufferedImage [] img = new BufferedImage[] { // вот это поле
ImageIO.read(new File("image/_1.png")),
ImageIO.read(new File("image/_2.png"))
};,
занимается именно этим -- создается массив из двух элементов (не анонимный -- у него есть имя -- img
!), для каждого из них вызывается метод read()
, который возвращает значение, которое и присваивается элементу массива.
Анонимный класс отличается от нормального тем, что у него нет имени, а значит, нельзя описать переменную такого класса, а значит, нет честного способа обратиться извне к тем его полям и методам, которые не описаны в родительском классе. Но описанные в нем методы (в том числе переопределенные методы родительского класса) вполне могут к ним обращаться, например, в вашем коде это g.drawImage(img[0],0,0,null);
.
Так что конструкция вида
MyClass myVar = new MyClass() {
int number = 123;
String name = new String("Это объект № ");
@Override
public String toString() {
return name + number;
}
public void foolish() {
System.out.println("Этот метод не может быть вызван");
}
}
равносильна описанию
class NewClass extends MyClass {
int number = 123;
String name = new String("Это объект № ");
@Override
public String toString() {
return name + number;
}
public void foolish() {
System.out.println("Этот метод не может быть вызван");
}
}
NewClass myVar = new NewClass();
за исключением того, что в случае обычного класса вы можете вызвать вновь описанный метод
myVar.foolish();
а в случае анонимного класса вы этого сделать не можете, поскольку переменная myVar
относится к типу MyClass
, который такого метода не содержит.
Это не поля класса. Просто создаётся массив экземпляров класса BufferedImage
. Вызов метода ImageIO.read(new File("image/_1.png"))
, скорее всего, возвращает экземпляр этого класса. Переписал ваш код для наглядности:
public class some {
public static void main(String[] args) {
Other[] arrayOfOther = new Other[] {
new Other(),
new Other()
};
}
}
class Other{}
Update
Переписал для вас половину swing-a. Надеюсь будет понятней
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
JPanel contentPane = new JPanel() {
BufferedImage [] img = new BufferedImage[] { // вот это поле
ImageIO.read(),
ImageIO.read()
};
protected void paintComponent(String s) {
super.paintComponent(s);
System.out.println("Я метод класса-наследника. И да, я имею доступ к массиву `img` " + Arrays.toString(img));
}
};
contentPane.paintComponent("");
}
}
// "Оригинальный" класс JPanel. Понятия ни имеет о массиве `BufferedImage [] img`
class JPanel {
protected void paintComponent(String s) {
System.out.println("Я метод родительского класса. Меня вызвали. Ура");
}
}
class BufferedImage {
public String toString() {
return "Красивая картинка";
}
}
class ImageIO {
static BufferedImage read() {
return new BufferedImage();
}
}
Попробуйте запустить эту программу.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Не могу понять в чем может быть ошибка при удалении
Занимаюсь получением http запроса, я вроде как пробился на сайт, но получаю след ошибки:
Я пишу файловое хранилище и хочу улучшить его работуЗагружаются файлы большого размера, кроме этого, после загрузки надо запретить их изменение,...