Основная задача конструкторов заключается в том, чтобы установить объект в первоначальное состояние, когда он создается при помощи оператора 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.
}
Классы и методы | Правила видимости |