Java независимый блок кода
Я давно работаю с Java, но никогда не сталкивался с чем-то подобным. Я хотел бы знать, что он делает и почему это не ошибка.
public class Foo{
private int someVariable;
{
doSomething();
}
public Foo(){
}
private void doSomething(){
// Something is done here
}
}
Я хотел бы знать, какова цель отдельного блока, который содержит вызов "doSomething()". Это просто скелетный код. Фактический код, с которым я столкнулся, находится по адресу http://www.peterfranza.com/2010/07/15/gwt-scrollpanel-for-touch-screens/
2 ответа
Это (нестатический) блок инициализатора. Это задокументировано в официальном руководстве здесь:
Инициализация членов экземпляра
Обычно вы помещаете код для инициализации переменной экземпляра в конструкторе. Существует две альтернативы использованию конструктора для инициализации переменных экземпляра: блоки инициализатора и финальные методы. Блоки инициализатора для переменных экземпляра выглядят так же, как статические блоки инициализатора, но без ключевого слова static:
{ // whatever code is needed for initialization goes here }
Компилятор Java копирует блоки инициализатора в каждый конструктор. Следовательно, этот подход можно использовать для совместного использования блока кода между несколькими конструкторами.
Вот простая демонстрация:
public class Test {
{
System.out.println("Initializer block");
}
Test() {
System.out.println("Constructor 1");
}
Test(int i) {
System.out.println("Constructor 2");
}
public static void main(String[] args) {
new Test();
System.out.println("---");
new Test(1);
}
}
Выход:
Initializer block
Constructor 1
---
Initializer block
Constructor 2
Это может оказаться полезным, например, при добавлении JLabel
на панель:
panel.add(new JLabel() {{ setBackground(Color.GREEN); setText("Hello"); }});
Под капотом:
Байт-код блока инициализатора буквально копируется в каждый конструктор. (По крайней мере, Suns javac и компилятор eclipse:
Test();
Code:
0: aload_0
1: invokespecial
4: getstatic #2;
7: ldc #3; //String "Initializer block"
9: invokevirtual #4; //Method PrintStream.println:(String;)V
12: getstatic #2;
15: ldc #5;
17: invokevirtual #4;
20: return
Test(int);
Code:
0: aload_0
1: invokespecial #1;
4: getstatic #2;
7: ldc #3; //String "Initializer block"
9: invokevirtual #4; //Method PrintStream.println:(String;)V
12: getstatic #2;
15: ldc #6;
17: invokevirtual #4;
20: return
Это блок инициализатора, который копируется во все конструкторы класса.