Сомнения в основах 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();        
     }
 }

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

Ответ 1

Пусть выражается с более ясным примером:

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().

Ответ 3

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

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

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

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

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

Ответ 4

Подтяжки непосредственно внутри класса вводят инициализатор экземпляра (введенный в 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 и статические инициализаторы, выполняемые один раз, когда класс инициализируется, а не на основе каждого экземпляра.