Материал предоставлен https://it.rfei.ru

Конструкторы

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

<модификатор доступа> <имя класса> (<список формальных параметров>)
            <выражение throws> // заголовок конструктора
  { // тело конструктора
    <объявления локальных переменных>
    <объявления вложенных классов>
    <операторы>
  }

Объявление конструктора очень похоже на объявление метода. Однако следует обратить внимание на следующие ограничения.

  • Модификаторы, кроме модификаторов доступа, недопустимы в заголовке конструктора.
  • Конструктор не может возвращать значение, поэтому не может и задавать в заголовке возвращаемый тип, даже void, но простая форма оператора return может содержаться в теле конструктора.
  • Имя конструктора должно быть таким же, как и имя класса.

Имена классов и методов находятся в разных пространствах имен. Поэтому в примере 4.5 не будет конфликта имен, где метод, объявленный в строке (2), имеет такое же имя, как и конструктор, объявленный в строке (1). Однако использование подобной схемы именования строго не рекомендуется.

Пример 4.5. Пространство имен

public class Name {

    Name() {                    // (1)
        System.out.println("Constructor");
    }

    void Name() {               // (2)
        System.out.println("Method");
    }

    public static void main(String[] args) {
        new Name().Name();      // (3) за вызовом конструктора следует вызов метода
    }
}

Вывод программы:

Constructor
Method

Конструктор по умолчанию

Конструктор по умолчанию — это конструктор без каких-либо параметров. Другими словами, он имеет следующую сигнатуру:

<имя класса>()

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

<class name>() { super(); } // нет параметров, вызывает конструктор суперкласса.

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

В следующем коде класс Light не определяет никаких конструкторов.

class Light {
    // поля
    int     noOfWatts;       // Мощность
    boolean indicator;       // Включено или выключено
    String  location;        // Размещение

    // нет конструкторов
    //...
}

class Greenhouse {
    // ...
    Light oneLight = new Light();     // (1) вызов неявного конструктора по умолчанию
}

В предыдущем коде во время создания объекта Light в строке (1) используется неявный конструктор по умолчанию.

Light() { super(); }

При создании объекта при помощи оператора new с использованием конструктора по умолчанию, как в строке (1), поля объекта будут проинициализированы соответствующими значениями по умолчанию (т.е. поля noOfWatts, indicator и location в объекте Light будут проинициализированы 0, false и null соответственно).

Класс может самостоятельно предоставить реализацию конструктора по умолчанию. В следующем примере класс Light явно определяет в строке (1) конструктор по умолчанию. Обратите внимание, что он имеет такое же имя, как и класс, и не получает никаких параметров.

class Light {
    // ...
    // Explicit Default Constructor
    Light() {                        // (1)
        noOfWatts = 50;
        indicator = true;
        location  = "X";
    }
    //...
}

class Greenhouse {
    // ...
    Light extraLight = new Light();   // (2) Вызов явного конструктора по умолчанию
}

Наличие явного конструктора по умолчанию гарантирует, что в любом объекте, созданном с помошью выражения new Light(), как в строке (2), значения полей noOfWatts, indicator и location будут установлены в 50, true и "X" соответственно.

Если в классе определены какие-либо явные конструкторы, то он не может больше полагаться на неявный конструктор по умолчанию, для установки состояния объектов. Если в таком классе требуется конструктор по умолчанию, то должна быть его реализация. В примере ниже в классе Light задан только конструктор не по умолчанию (1). Он вызывается в строке (2), когда с помощью оператора new создается объект класса light. Любая попытка вызова конструктора по умолчанию будет обозначена как ошибка на этапе компиляции, как показано в строке (3).

class Light {
    // ...
    // Только конструктор не по умолчанию
    Light(int noOfWatts, boolean indicator, String location) {          // (1)
        this.noOfWatts = noOfWatts;
        this.indicator = indicator;
        this.location  = location;
    }
    //...
}
class Greenhouse {
    // ...
    Light moreLight  = new Light(100, true, "Greenhouse");   // (2) OK.
//  Light firstLight = new Light();                     // (3) Ошибка на этапе компиляции
}

Перегруженные конструкторы

Как и методы, конструкторы также могут быть перегружены. Так как все конструкторы в классе имеют такое же имя, как и имя класса, то их сигнатуры различаются по их спискам параметров. В следующем примере класс Light поддерживает как явную реализацию конструктора по умолчанию в строке (1), так и конструктор не по умолчанию (2). Конструкторы перегружены, как явно следует из их сигнатур. Конструктор не по умолчанию вызывается, когда создается объект класса Light в строке (3), подобным же образом вызывается и конструктор по умолчанию в строке (4).

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

class Light {
    // ...
    // Явный конструктор по умолчанию
    Light() {                                                  // (1)
        noOfWatts = 50;
        indicator = true;
        location  = "X";
    }

    // Конструктор не по умолчанию
    Light(int noOfWatts, boolean indicator, String location) { // (2)
        this.noOfWatts = noOfWatts;
        this.indicator = indicator;
        this.location  = location;
    }
    //...
}

class Greenhouse {
    // ...
    Light moreLight  = new Light(100, true, "Greenhouse");     // (3) OK.
    Light firstLight = new Light();                            // (4) OK.
}
Классы и методыПравила видимости