
3-й семестр / Лекции / 4 - Презентация 2 - ООП
.pdf
Центр дистанционного обучения
Вложенные классы
Таким образом, невозможно создать отдельно стоящий объект не-статического вложенного класса Point – он может быть создан только имея ссылку на объект Shape. При создании объекта Point внутри класса Shape компилятор неявно заполняет поле this$0 ссылкой this:
class Shape {
...
Point p = new Point(1, 2);
// Компилятор заменяет на new Point(this, 1, 2)
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
Для создания объектов не-статических вложенных классов извне класса Shape используется синтаксис:
Shape s1 = ...;
Shape.Point p1 = s1.new Point(1, 2);
// При этом p1.this$0 заполняется ссылкой на s1
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
Внутри не-статического вложенного класса можно ссылаться на поля и методы объемлющего класса. При этом эти методы вызываются у объекта this$0.
public class Shape {
public class Point {
public void test() {
System.out.println(getArea()); // Вызов this$0.getArea()
}
}
public double getArea() { return 0; }
}
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
public interface HasArea { double getArea();
}
Анонимные классы – всегда либо наследуются от базового класса, либо реализуют интерфейс.
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
HasArea squareMeter = new HasArea() { @Override
public double getArea() { return 1; }
};
Объект squareMeter принадлежит безымянному классу, реализующему интерфейс HasArea с реализацией метода getArea, возвращающей 1.
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
Анонимные классы могут захватывать переменные, доступные в области видимости:
public static void main(String[] args) { double side = 2;
HasArea square = new HasArea() { @Override
public double getArea() { return side * side; }
};
}
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
Захватываемые переменные должны быть effective final, т.е. быть присвоены только один раз. Если бы было разрешено менять переменные, то:
double side = 2;
HasArea square = new HasArea() {
@Override double getArea() { return side * side; }
};
side = 3; // Что теперь возвращает square.getArea()?
// Либо 4, либо 9. Для устранения неоднозначности
// менять захватываемые переменные запрещено
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
public class Example {
private double getSide() { return 2;
}
public void test() {
HasArea square = new HasArea() { @Override
public double getArea() {
//Анонимный класс может ссылаться на
//методы и поля объемлющего класса return getSide() * getSide();
}
}; System.out.println(square.getArea());
}
} |
online.mirea.ru |
|

Центр дистанционного обучения
Вложенные классы
public class Example {
private double getSide() { return 2;
}
public void test() {
HasArea rectangle = new HasArea() { public double getSide() {
return 3;
}
@Override
public double getArea() {
return this.getSide() * // обращение к методу анонимного класса Example.this.getSide(); // обращение к методу объемлющего класса
}
};
}
}
online.mirea.ru

Центр дистанционного обучения
Вложенные классы
Если анонимный класс реализует интерфейс с одим методом, то его запись может быть сокращена:
HasArea square1 = new HasArea() {
@Override public double getArea() { return 1; }
}
HasArea square2 = () -> { return 1; }
HasArea square3 = () -> 1;
Это так называемые лямбда-выражения.
online.mirea.ru