Чем инициализатор экземпляра отличается от конструктора?

Другими словами, зачем вам нужен инициализатор экземпляра? Какая разница или преимущество у вас в написании инициализатора экземпляра над конструктором?

6 ответов

Решение

Это, кажется, объясняет это хорошо:

Инициализаторы экземпляров являются полезной альтернативой инициализаторам переменных экземпляров всякий раз, когда:

  • код инициализатора должен перехватывать исключения, или

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

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

От: JavaWorld Инициализация объекта в Java.

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

Семантически, инициализатор - это хороший инструмент по нескольким причинам:

инициализатор может улучшить читаемость кода, оставив логику инициализации рядом с инициализируемой переменной:

   public class Universe {
       public int theAnswer;
       {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;
       }

       // a bunch of other vars
   }

против

   public class Universe {
       public int theAnswer;

       // a bunch of other vars

       public Universe() {
         int SIX = 6;
         int NINE = 7;
         theAnswer = SIX * NINE;

         // other constructor logic
       }
   }

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

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

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

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

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

Реальное преимущество инициализаторов экземпляров перед конструкторами видно, когда мы используем анонимный внутренний класс.

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

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

Мы не можем заменить конструктор блоком экземпляра, потому что конструктор может принимать аргументы, но блок экземпляра не может принимать аргументы.

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

Пример:

class MyClass{

    static int object_count = 0;

    MyClass(){
        object_count++;
    }

    MyClass(int i){

        object_count++;
    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

Выход: 2

class MyClass{

    static int object_count = 0;

    {
        object_count++;
    }

    MyClass(){

    }

    MyClass(int i){     

    }

    void getCount() {

        System.out.println(object_count);
    }

    public static void main(String... args) {
        MyClass one = new MyClass();
        MyClass two = new MyClass(2);
        two.getCount();
    }
}

Выход: 2

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

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

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