5.03. Прочие особенности языка Java
Прочие особенности языка Java
Анонимные классы
★ Анонимный класс – это локальный внутренний класс без имени, который создаётся и используется сразу при объявлении. Он используется для реализации интерфейсов или абстрактных классов на лету, к примеру, при использовании слушателей событий, например, в GUI или коллбэках.
Пример:
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
Greeting greet = new Greeting() {
public void sayHello() {
System.out.println("Hello from anonymous class!");
}
};
greet.sayHello();
}
}
Другой пример:
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Clicked!");
}
});
Таким образом, анонимный класс — это безымянный внутренний класс, объявляемый и создающийся в момент использования.
Varargs
Varargs – методы с переменным числом аргументов.
★ Методы с переменным числом аргументов (varargs) принимают произвольное количество аргументов одного типа.
Пример:
public void printNumbers(int... numbers) {
for (int num : numbers) {
System.out.println(num);
}
}
Вызов:
printNumbers(1, 2, 3);
printNumbers();
printNumbers(new int[]{1, 2, 3});
То есть, varargs это в нашем случае numbers, который должен быть последним параметром в списке аргументов метода.
final
final – неизменяемость полей, методов и классов.
Если переменная объявлена как final, её значение нельзя изменить после инициализации.
final double PI = 3.14159;
PI = 3.14; // Ошибка компиляции
Для ссылочных типов нельзя изменить саму ссылку, но можно изменить состояние объектов:
final List<String> list = new ArrayList<>();
list.add("Hello"); // правильно
list = new ArrayList<>(); // неправильно
★ Метод, помеченный как final, нельзя переопределять в подклассе.
class Parent {
final void doNotOverride() {
System.out.println("This method cannot be overridden");
}
}
class Child extends Parent {
void doNotOverride() { } // Ошибка
}
Класс, объявленный как final, нельзя наследовать:
final class FinalClass { }
class SubClass extends FinalClass { } // Ошибка
this и super
this и super – работа с контекстом класса.
Ключевое слово this ссылается на текущий объект, может вызывать другой конструктор в том же классе – this(…);
this — это ссылка на текущий объект внутри его нестатического метода или конструктора.
Она используется, чтобы
- сослаться на поля класса, если локальные переменные или параметры метода имеют такое же имя;
- вызвать другой конструктор в том же классе;
- передать текущий объект как аргумент другому методу или объекту.
Ключевое слово super ссылается на объект родительского класса, вызывает конструктор или метод родителя – super(…), как в примере выше.
Автоупаковка и автораспаковка
★ Автоупаковка (Autoboxing) – автоматическое преобразование значения типа-примитива (int, double, boolean) в соответствующий ему объект класса-обёртки (Integer, Double, Boolean).
Пример:
Integer number = 10; // int → Integer (автоупаковка)
Компилятор сам вызовет следующее:
Integer number = Integer.valueOf(10);
★ Автораспакова (Unboxing) – обратный процесс: автоматическое преобразование объекта класса-обёртки в примитивный тип. Пример:
Integer age = 25;
int primitiveAge = age; // Integer → int (автораспаковка)
Компилятор сам вызывает:
int primitiveAge = age.intValue();
Это используется в методах, принимающих или возвращающих обёртки, и при работе с коллекциями вроде:
List<Integer> numbers = new ArrayList<>();
numbers.add(5); // автоупаковка int → Integer
int x = numbers.get(0); // автораспаковка Integer → int
Но к коллекциям мы вернёмся позднее.
Безымянные пакеты
★ Безымянные пакеты. Пакеты содержат дополнительные возможности, для использования которых нужно добавлять их в код. Кроме того, как можно было заметить выше, в начале кода всегда была строчка:
package com.test.mavenproject1
Но что, если её не будет?
В таком случае (без строки package) класс автоматически попадает в безымянный (default, по умолчанию) пакет. Все классы без указания package находятся в одном общем безымянном пакете. Это удобно для простых примеров или тестирования, но в реальных проектах так делать нельзя – должен быть порядок. Для организации структуры проекта всегда нужно группировать всё по пакетам, и особенно если может быть конфликт имён. Современные IDE даже ругаются (запрещают) компилировать классы из безымянного пакета в модульных проектах (к примеру, Java Platform Module System).
Из безымянного пакета импортировать данные нельзя, следовательно, если будет класс:
public class Calculator {
public int add(int a, int b) {
return a + b;
}
}
…то как бы мы ни пытались:
import Calculator; //Ошибка
import .Calculator; //Тоже ошибка
Поэтому, импорт будет работать только с именованными пакетами, а класс должен быть в каком-то конкретном пакете.
Классы, находящиеся в одном пакете, могут обращаться друг к другу без использования оператора import – то есть видят друг друга напрямую. Если в разных пакетах – без импорта не обойтись.
Методы по умолчанию в интерфейсах
Методы по умолчанию (Default Methods) в интерфейсах появились в Java 8, и позволяют добавлять реализацию по умолчанию в интерфейс, не нарушая совместимость.
Пример:
interface Logger {
default void log(String message) {
System.out.println("Log: " + message);
}
}