Constructors
Filling fields one by one after new is inconvenient, and it is easy to forget something. A constructor solves this: it receives the data and prepares the object right when it is created.
The first constructor
A constructor is a special method that is called by the new operator. Its name matches the class name, and no return type is written:
class User {
String name;
User(String n) {
name = n;
}
}
void main() {
User user = new User("Anna");
IO.println(user.name);
}Output:
AnnaThe arguments in parentheses after new User are passed to the constructor's parameters.
The this keyword
It is convenient to give a constructor parameter the same name as the field. Then the name name inside the constructor means the parameter, and the field is reached through this — a reference to the current object:
class User {
String name;
int age;
User(String name, int age) {
this.name = name;
this.age = age;
}
}
void main() {
User user = new User("Oleg", 30);
IO.println(user.name + ", " + user.age);
}Output:
Oleg, 30Several constructors
A class may have several constructors with different parameters — the same overloading that ordinary methods have. Java picks a constructor by its arguments:
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("Book", 12.5);
Product gift = new Product("Postcard");
IO.println(book.title + ": " + book.price);
IO.println(gift.title + ": " + gift.price);
}Output:
Book: 12.5
Postcard: 0.0The this(...) call hands the work over to another constructor of the same class, so the code that assigns fields is not repeated.
The default constructor
If a class has no constructors at all, Java adds an empty constructor without parameters by itself. That is why new User() worked in the previous lesson:
class Counter {
int value;
}
void main() {
Counter counter = new Counter();
counter.value++;
IO.println(counter.value);
}Output:
1Validation in the constructor
A constructor is a good place to keep wrong data out. If a value does not fit, you can throw an exception, and the object will not be created:
class Account {
double balance;
Account(double balance) {
if (balance < 0) {
throw new IllegalArgumentException("Balance cannot be negative");
}
this.balance = balance;
}
}
void main() {
Account account = new Account(100);
IO.println(account.balance);
new Account(-5);
}Output:
100.0
Exception in thread "main" java.lang.IllegalArgumentException: Balance cannot be negativeExceptions are covered in detail in the chapter on errors.
Common mistake
As soon as a class has at least one constructor of its own, the empty default constructor is no longer added. A call without arguments stops compiling:
class User {
String name;
User(String name) {
this.name = name;
}
}
void main() {
User user = new User();
}Output:
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 is the full name of the class: in the file Main.java all declared classes end up inside the implicit class Main. If you need that call too, declare a constructor without parameters explicitly.