Разъяснения по основам Java?

class test {

    test() {
        System.out.println("Constructor");
    }

    {
        System.out.println("Hai");
    }

}

public class sample {

    public static void main(String [] a) {
        test t = new test();        
    }

}

в вышеприведенном коде почему оператор, заключенный в фигурные скобки ((то есть) "Hai"), печатается до выполнения конструктора.

4 ответа

Решение

Позвольте выразить более наглядным примером:

public class Test {

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

    {
         System.out.println("instance initializer");
    }

    public Test() {
         System.out.println("constructor");
    }

}

и проверьте это следующим образом:

public class Main {

    public static void main(String[] args) {
        Test test1 = new Test();
        Test test2 = new Test();
    }

}

выход:

static initializer
instance initializer
constructor
instance initializer
constructor

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

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

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

Основным преимуществом статических инициализаторов является то, что они выполняются только один раз во время загрузки класса. Хорошо известным примером из реальной жизни является драйвер JDBC. Когда вы делаете

 Class.forName("com.example.jdbc.Driver");

который выполняет только static инициализатора, тогда любой (приличный) драйвер JDBC зарегистрирует себя в DriverManager следующее

 static {
      DriverManager.registerDriver(new com.example.jdbc.Driver());
 }

таким образом DriverManager можно найти правильный драйвер JDBC во время getConnection(),

Да. Это инициализатор экземпляра. Он запускается, как только создается экземпляр класса.

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

Потому что это ожидаемое поведение, как описано в разделе 12.5 Создание новых экземпляров классов спецификации языка Java:)

Непосредственно перед тем, как ссылка на вновь созданный объект возвращается в качестве результата, указанный конструктор обрабатывается для инициализации нового объекта с помощью следующей процедуры:

  1. Присвойте аргументы конструктора вновь созданным переменным параметра для этого вызова конструктора.
  2. Если этот конструктор начинается с явного вызова конструктора другого конструктора в том же классе (используя this), затем оцените аргументы и обработайте этот вызов конструктора рекурсивно, используя те же пять шагов. Если этот вызов конструктора завершается внезапно, то эта процедура завершается преждевременно по той же причине; в противном случае перейдите к шагу 5.
  3. Этот конструктор не начинается с явного вызова конструктора другого конструктора в том же классе (используя this). Если этот конструктор предназначен для класса, отличного от Object, тогда этот конструктор начнется с явного или неявного вызова конструктора суперкласса (используя super). Оцените аргументы и обработайте этот вызов конструктора суперкласса рекурсивно, используя те же пять шагов. Если этот вызов конструктора завершается преждевременно, то эта процедура завершается преждевременно по той же причине. В противном случае перейдите к шагу 4.
  4. Выполните инициализаторы экземпляров и инициализаторы переменных экземпляра для этого класса, присваивая значения инициализаторов переменных экземпляра соответствующим переменным экземпляра, в порядке слева направо, в котором они появляются текстово в исходном коде для класса. Если выполнение какого-либо из этих инициализаторов приводит к исключению, то дальнейшие инициализаторы не обрабатываются, и эта процедура резко завершается с тем же исключением. В противном случае перейдите к шагу 5. (В некоторых ранних реализациях компилятор неправильно пропускал код для инициализации поля, если выражение инициализатора поля было константным выражением, значение которого было равно значению инициализации по умолчанию для его типа.)
  5. Выполните остальную часть тела этого конструктора. Если это выполнение завершается внезапно, то эта процедура завершается преждевременно по той же причине. В противном случае эта процедура завершается нормально.

Смотрите раздел 8.6 Инициализаторы экземпляра для более подробной информации о... инициализаторах экземпляра.

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

 private final Thing x = new Thing();

а также

 private final Thing x;
 {
     x = new Thing();
 }

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

 private final Thing x;
 public MyCLass() {
     super(); // Often implicit.
     x = new Thing();
 }

Брекеты в той же позиции, которой предшествует static ключевые слова и статические инициализаторы, выполняемые один раз при инициализации класса, а не для каждого экземпляра.

Другие вопросы по тегам