Почему этот код Java находится в фигурных скобках ({}) вне метода? - PullRequest
28 голосов
/ 03 мая 2011

Я готовлюсь к сертификационному экзамену Java, и я видел код, похожий на этот в одном из практических тестов:

class Foo {  
    int x = 1;  
    public static void main(String [] args) {  
        int x = 2;  
        Foo f = new Foo();  
        f.whatever();  
    }  
    { x += x; }  // <-- what's up with this?
    void whatever() {  
        ++x;  
        System.out.println(x);  
    }  
}

Мой вопрос ... Допустимо ли писать код в фигурных скобках вне метода? Каковы последствия этих (если таковые имеются)?

Ответы [ 3 ]

34 голосов
/ 03 мая 2011

Заимствовано из здесь -

Обычно вы бы помещали код для инициализации переменной экземпляра в конструкторе.Существует две альтернативы использованию конструктора для инициализации переменных экземпляра: блоки инициализатора и финальные методы.Блоки инициализатора для переменных экземпляра выглядят так же, как статические блоки инициализатора, но без ключевого слова static:

{
    // whatever code is needed for initialization goes here
} 

Компилятор Java копирует блоки инициализатора в каждый конструктор.Следовательно, этот подход можно использовать для разделения блока кода между несколькими конструкторами.

Вы также можете посмотреть обсуждения здесь .

10 голосов
/ 03 мая 2011

Это блок инициализатора, который выполняется во время загрузки / создания экземпляра класса и который используется для инициализации свойств члена класса (см. Java http://download.oracle.com/javase/tutorial/java/javaOO/initial.html).. Вы можете иметь столько блоков, сколько хотите, и они будут созданы сверху вниз.

В дополнение к блоку экземпляра вы можете иметь столько статических блоков, сколько захотите, а также инициализировать статические элементы. Они будут объявлены следующим образом:

public class Initialization {

    static int b = 10;

    int a = 5;

    static {
        b = -9;
    }

    {
        a += 2;
    }

    public static void main(String[] args) throws Exception {

        System.out.println(ClientVoting.b);
        System.out.println(new ClientVoting().a);
        System.out.println(ClientVoting.b);
        System.out.println(new ClientVoting().a);

    }

    static {
        b = 1;
    }

    {
        a++;
    }
}

Пока класс инициализируется, статический член "b" инициализируется как 10, затем первая статическая область видимости изменяет свое значение на -9, а затем на 1. Это выполняется только один раз, пока класс загружается. Это выполняется перед инициализацией первой строки основного метода.

С другой стороны, аналогичным примером для вашего класса является ссылка на экземпляр "a". A инициализируется как 5, затем блок экземпляра обновляет его до 7, а последний блок - до 8. Как и ожидалось, статические члены инициализируются в этом коде только один раз, в то время как блоки экземпляра выполняются КАЖДЫЙ раз, когда вы создаете новый экземпляр.

Выходные данные для этого примера: 1 8 1 8

7 голосов
/ 03 мая 2011

Это блок инициализатора . Он используется для установки переменных экземпляра. Мотивация использовать блоки инициализатора над конструкторами состоит в том, чтобы предотвратить написание избыточного кода. Компилятор Java копирует содержимое блока в каждый конструктор.

...