Виклик методу 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

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

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.