В чем смысл "инициализаторов экземпляра" на Java?
Разве мы не можем просто поместить этот блок кода в начало конструктора?
Почему java Instance инициализаторы?
Ответ 1
Я использую их очень часто, как правило, для создания и заполнения Карты в одном выражении (вместо использования уродливого статического блока):
private static final Map<String, String> CODES = new HashMap<String, String>() {
{
put("A", "Alpha");
put("B", "Bravo");
}
};
Одно интересное и полезное приукрашивание - создание немодифицируемой карты в одном утверждении:
private static final Map<String, String> CODES =
Collections.unmodifiableMap(new HashMap<String, String>() {
{
put("A", "Alpha");
put("B", "Bravo");
}
});
Путь более аккуратный, чем использование статических блоков и обращение к сингулярным назначениям для окончательного и т.д.
И еще один совет: не бойтесь создавать методы, которые упрощают ваш блок экземпляра:
private static final Map<String, String> CODES = new HashMap<String, String>() {
{
put("Alpha");
put("Bravo");
}
void put(String code) {
put(code.substring(0, 1), code);
}
};
Ответ 2
Вы действительно можете поставить код в начале каждого конструктора. Однако именно эта точка инициализатора экземпляра: его код применяется ко всем конструкторам, что может быть удобно, если у вас есть много конструкторов и немного кода, который является общим для всех них.
(Если вы только начинаете с программирования, возможно, вы не знали, что можно создать много конструкторов для одного и того же класса (если они принимают разные параметры), это называется перегрузкой конструктора. только один конструктор, то инициализатор экземпляра действительно не очень полезен (Edit: Если вы не злоупотребляете им в творческой моде, как показано в других ответах).
Ответ 3
Вы можете использовать инициализатор экземпляра при объявлении анонимного класса, например, при совершении Идиомы двойного выравнивания брака.
List<String> mylist = new ArrayList<String>(){{add("a"); add("b"); add("c");}};
Здесь вы можете инициализировать объект, даже если вы ничего не можете добавить к конструктору (потому что класс анонимный).
Ответ 4
Поскольку все примеры кода здесь используют анонимные классы, я собрал этот (слегка ужасающий) класс, который демонстрирует использование инициализаторов экземпляра в "правильном" классе. Вы можете использовать их для выполнения сложной обработки или обработки исключений во время инициализации. Обратите внимание, что эти блоки запускаются до запуска конструктора, , но конструктор запускается до запуска инициализаторов в дочернем классе:
import java.util.Scanner;
public class InstanceInitializer {
int x;
{
try {
System.out.print("Enter a number: ");
x = Integer.parseInt(new Scanner(System.in).nextLine());
} catch (NumberFormatException e) {
x = 0;
}
}
String y;
{
System.out.print("Enter a string: ");
y = new Scanner(System.in).nextLine();
for(int i = 0; i < 3; i++)
y += y;
}
public InstanceInitializer() {
System.out.println("The value of x is "+x);
System.out.println("The value of y is "+y);
}
public static class ChildInstanceInitializer extends InstanceInitializer {
{
y = "a new value set by the child AFTER construction";
}
}
public static void main(String[] args){
new InstanceInitializer();
new InstanceInitializer();
System.out.println();
System.out.println(new ChildInstanceInitializer().y);
// This is essentially the same as:
System.out.println(new InstanceInitializer(){
{y = "a new value set by the child AFTER construction";}
}.y);
}
}
Этот вывод (что-то вроде):
Enter a number: 1
Enter a string: a
The value of x is 1
The value of y is aaaaaaaa
Enter a number: q
Enter a string: r
The value of x is 0
The value of y is rrrrrrrr
Enter a number: 3
Enter a string: b
The value of x is 3
The value of y is bbbbbbbb
a new value set by the child AFTER construction
Enter a number: s
Enter a string: Hello
The value of x is 0
The value of y is HelloHelloHelloHelloHelloHelloHelloHello
a new value set by the child AFTER construction
Обратите внимание, что строка "новое значение" не установлена до тех пор, пока уже не будет вызван конструктор родительского класса.