Конструкторы
Заполнять поля по одному после new неудобно, и легко что-то забыть. Конструктор решает эту задачу: он получает данные и готовит объект сразу при создании.
Первый конструктор
Конструктор — это особый метод, который вызывается оператором new. Его имя совпадает с именем класса, а тип результата не указывается:
class User {
String name;
User(String n) {
name = n;
}
}
void main() {
User user = new User("Анна");
IO.println(user.name);
}Результат:
АннаАргументы в скобках после new User передаются в параметры конструктора.
Ключевое слово this
Параметр конструктора удобно называть так же, как поле. Тогда имя name внутри конструктора означает параметр, а к полю обращаются через this — ссылку на текущий объект:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
}
void main() {
User user = new User("Олег", 30);
IO.println(user.name + ", " + user.age);
}Результат:
Олег, 30Несколько конструкторов
В классе может быть несколько конструкторов с разными параметрами — это та же перегрузка, что и у обычных методов. Java выбирает конструктор по аргументам:
class Product {
String title;
double price;
Product(String title, double price) {
this.title = title;
this.price = price;
}
Product(String title) {
this(title, 0.0);
}
}
void main() {
Product book = new Product("Книга", 12.5);
Product gift = new Product("Открытка");
IO.println(book.title + ": " + book.price);
IO.println(gift.title + ": " + gift.price);
}Результат:
Книга: 12.5
Открытка: 0.0Вызов this(...) передаёт работу другому конструктору того же класса, поэтому код присваивания полей не повторяется.
Конструктор по умолчанию
Если в классе нет ни одного конструктора, Java сама добавляет пустой конструктор без параметров. Именно поэтому в прошлом уроке работало new User():
class Counter {
int value;
}
void main() {
Counter counter = new Counter();
counter.value++;
IO.println(counter.value);
}Результат:
1Проверка в конструкторе
Конструктор — хорошее место, чтобы не допустить неверных данных. Если значение не подходит, можно выбросить исключение, и объект не будет создан:
class Account {
double balance;
Account(double balance) {
if (balance < 0) {
throw new IllegalArgumentException("Баланс не может быть отрицательным");
}
this.balance = balance;
}
}
void main() {
Account account = new Account(100);
IO.println(account.balance);
new Account(-5);
}Результат:
100.0
Exception in thread "main" java.lang.IllegalArgumentException: Баланс не может быть отрицательнымПодробнее об исключениях — в главе об ошибках.
Частая ошибка
Как только в классе появился хотя бы один свой конструктор, пустой конструктор по умолчанию больше не добавляется. Вызов без аргументов перестаёт компилироваться:
class User {
String name;
User(String name) {
this.name = name;
}
}
void main() {
User user = new User();
}Результат:
Main.java:10: error: constructor User in class Main.User cannot be applied to given types;
User user = new User();
^
required: String
found: no arguments
reason: actual and formal argument lists differ in lengthMain.User — полное имя класса: в файле Main.java все объявленные классы оказываются внутри неявного класса Main.
Если нужен и такой вызов, объявите конструктор без параметров явно.