Вызов метода Java без имени


101

Я смотрел на приведенный ниже код и обнаружил что-то странное:

public class Sequence {
    Sequence() {
        System.out.print("c ");
    }

    {
        System.out.print("y ");
    }

    public static void main(String[] args) {
        new Sequence().go();
    }

    void go() {
        System.out.print("g ");
    }

    static {
        System.out.print("x ");
    }
}

Я ожидал, что это приведет к ошибке компиляции, так как System.outс "y" не принадлежит просто объявлению метода a { }. Почему это действительно так? Я не понимаю, как этот код должен или должен называться.

При запуске он x y c gтакже производит , почему вызывается static { }перед конструктором последовательности?

Ответы:


149

Это:

static {
        System.out.print("x ");
    }

является статическим блоком инициализации и вызывается при загрузке класса. Вы можете иметь столько их в своем классе, сколько хотите, и они будут выполняться в порядке их появления (сверху вниз).

Это:

    {
        System.out.print("y ");
    }

это блок инициализации , и код копируется в начало каждого конструктора класса. Итак, если у вас много конструкторов вашего класса, и все они должны делать что-то общее в начале, вам нужно всего лишь один раз написать код и поместить его в блок инициализации, подобный этому.

Следовательно, ваш вывод имеет смысл.

Как сказал Стэнли ниже, см. Раздел в руководстве Oracle, описывающий блоки инициализации, для получения дополнительной информации.


12
Отличный ответ. Узнайте больше о блоке инициализации на http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Стэнли,

6
the code is copied into the beginning of each constructor of the class- это неверно. Скажем, конструктор начинается с super("x ");, суперконструктор будет выполняться до любых блоков инициализации.
RokL 05

3
да, сначала будут выполняться неявные и явные вызовы суперконструктора, затем блок инициализации, а затем остальной код конструктора.
jlordo 05

25

Это не метод, а блок инициализации .

 {
    System.out.print("y ");
 }

Он будет выполнен перед вызовом конструктора. Пока

static {
        System.out.print("x ");
       }

- статический блок инициализации, который выполняется, когда класс загружается загрузчиком классов.

Итак, когда вы запускаете свой код
1. Класс загружается загрузчиком классов, поэтому выполняется статический блок инициализации.
Вывод: x выводится на печать.
2. Объект создается, поэтому выполняется блок инициализации, а затем вызывается конструктор.
Вывод: выводится y, за которым следует c
3. Вызывается основной метод, который, в свою очередь, вызывает метод go
Вывод: выводится g.

Конечный результат: xycg
Это может помочь http://blog.sanaulla.info/2008/06/30/initialization-blocks-in-java/


@Cthulhu: Спасибо. Он действовал до прошлой недели, я обновил его новой ссылкой.
xyz

16

Это блок инициализации экземпляра, за которым следует блок статической инициализации .

{
    System.out.print("y ");
}

вызывается при создании экземпляра класса.

static {
    System.out.print("x ");
}

вызывается, когда класс загружается загрузчиком классов. Итак, когда вы это сделаете

new Sequence().go();

класс загружается, поэтому он выполняется static {}, затем он выполняет блок инициализации экземпляра {}, после этого вызывается тело конструктора, а затем метод для вновь созданного экземпляра. Ergo вывод x y c g.


15
static {
        System.out.print("x ");
    }

Это статический блок, который вызывается во время загрузки класса.

{
    System.out.print("y ");
}

Является ли блок инициализации

У вас может быть несколько блоков инициализации в классе, и в этом случае они выполняются в той последовательности, в которой они появляются в классе.

Обратите внимание, что любой блок инициализации, присутствующий в классе, выполняется перед конструктором.


10
static {
      System.out.print("x ");
}

- это блок инициализации, совместно используемый классом (как обозначено static), который выполняется первым.

{
        System.out.print("y ");

}

- это блок инициализации, общий для всех объектов (конструкторов) класса, который идет дальше.

Sequence() {
        System.out.print("c ");
}

- это особый конструктор класса, который выполняется третьим. Блок инициализации экземпляра вызывается первым при каждом выполнении конструктора. Вот почему "y" стоит перед "c".

void go() {
        System.out.print("g ");
}

- это просто метод экземпляра, связанный с объектами, созданными с использованием конструктора выше, который идет последним.


9
{
    System.out.print("y ");
}

Такие блоки называются initializer block. Он выполняется каждый раз, когда вы создаете экземпляр class. Во время компиляции этот код перемещается в каждый конструктор вашего класса.

Где как в случае static initializerблокировки: -

static {
    System.out.println("x ");
}

он выполняется один раз при загрузке класса. Обычно мы используем staticблок инициализатора, когда инициализация staticполя требует нескольких шагов.


6

Он используется как блок инициализации и запускается после любого статического объявления . Его можно использовать, чтобы гарантировать, что никто другой не сможет создать экземпляр класса (точно так же, как вы использовали бы частный конструктор), как в шаблоне проектирования Singleton .


3
static {
    System.out.print("x ");
}

Static blocksвыполняются только один раз при загрузке класса и инициализируется JRE.

И non-staticблок будет вызываться каждый раз, когда вы создаете новый экземпляр, и он будет вызываться непосредственно перед конструктором.

Поскольку здесь вы создали только 1 экземпляр, созданный Sequenceтаким образом, был вызван после non-staticблоков, а затем метод, который на самом деле является вашей целью.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.