Por que os construtores existem
Na página anterior, você criou classes e objetos com new. Um construtor é o código que de fato é executado durante essa chamada a new. Seu único objetivo é devolver um objeto pronto para uso: com todos os campos obrigatórios definidos e sem nenhum estado pela metade.
Um construtor se parece com um método, mas com duas diferenças: ele tem o mesmo nome da classe e não tem tipo de retorno, nem mesmo void.
new Point(3, 4) aloca o objeto e depois executa o corpo do construtor com x = 3 e y = 4. Quando new retorna, p já está totalmente inicializado.
A palavra-chave this
Dentro do construtor acima, os parâmetros se chamam x e y, os mesmos nomes dos campos. this.x significa "o campo x que pertence a este objeto", enquanto x puro se refere ao parâmetro. Sem this, x = x apenas atribuiria o parâmetro a si mesmo e deixaria o campo intocado.
Você só precisa de this quando um parâmetro oculta um campo, mas muita gente o usa em todo lugar por clareza. O erro comum é esquecê-lo quando os nomes coincidem: o código compila, executa e silenciosamente deixa seus campos com os valores padrão (null, 0, false).
O construtor padrão
Se você nunca escrever um construtor, o Java fornece discretamente um construtor padrão: um construtor público, sem argumentos, que não faz nada a mais. Por isso new funcionava em classes que não tinham construtor algum.
A pegadinha: assim que você escreve qualquer construtor, o gratuito some.
class Box {
int size;
Box(int size) { // agora NÃO há construtor sem argumentos
this.size = size;
}
}
new Box(); // erro de compilação: o construtor Box() não existe
Se você ainda quiser que new Box() funcione, declare você mesmo o construtor sem argumentos:
Sobrecarga de construtores
Uma classe pode ter vários construtores desde que suas listas de parâmetros sejam diferentes: isso é apenas a sobrecarga de métodos aplicada aos construtores. Cada um oferece uma maneira diferente de construir o objeto.
O Java escolhe o construtor correspondente pelo número e pelos tipos dos argumentos que você passa para new.
Encadeamento com this()
Repare na duplicação acima: cada construtor atribui os campos por conta própria. Você pode evitar isso fazendo um construtor chamar outro com this(...). A chamada deve ser a primeira instrução do construtor.
Agora a inicialização de fato fica em um só lugar. Os construtores menores apenas preenchem os valores padrão e repassam o trabalho. Se você algum dia tentar colocar uma instrução antes de this(...), o compilador a rejeita.
Construtores e super()
Todo construtor chama implicitamente o construtor da superclasse primeiro. Se você não escrever nada, o Java insere um super() oculto (o construtor sem argumentos da superclasse) no topo do corpo. Você trabalhará com isso diretamente assim que começar a criar subclasses, que é o próximo tópico.
class Animal {
String name;
Animal(String name) { this.name = name; }
}
class Dog extends Animal {
Dog(String name) {
super(name); // aqui é preciso chamar o construtor do pai explicitamente
}
}
Como Animal não tem construtor sem argumentos, Dog precisa chamar super(name) explicitamente: não há um super() gratuito para recorrer. Assim como this(), uma chamada a super(...) tem que ser a primeira instrução do construtor.
Próximo: Herança
Os construtores inicializam um único objeto, mas super() já deu uma pista de algo maior: as classes podem se basear em outras classes, reutilizando seus campos, métodos e construtores. Essa relação, uma classe estendendo outra, é a herança, e é a próxima página.
Perguntas frequentes
O que é um construtor em Java?
Um construtor é um método especial que é executado quando você cria um objeto com new. Ele tem o mesmo nome da classe e nenhum tipo de retorno (nem mesmo void). Sua função é colocar o novo objeto em um estado inicial válido, normalmente atribuindo os argumentos do construtor aos campos do objeto.
Qual é a diferença entre um construtor e um método em Java?
Um construtor tem exatamente o mesmo nome da classe e não declara nenhum tipo de retorno, e só pode ser invocado com new quando um objeto é criado. Um método comum tem seu próprio nome, declara um tipo de retorno (ou void) e é chamado em um objeto já existente. Construtores inicializam; métodos realizam o trabalho depois.
O que acontece se eu não escrever um construtor em Java?
O compilador fornece de graça um construtor padrão sem argumentos que não recebe parâmetros e não faz nada além da chamada implícita a super(). Mas no momento em que você escreve qualquer construtor por conta própria, esse construtor gratuito desaparece. Portanto, se você adicionar um construtor parametrizado e ainda quiser que new Thing() funcione, deve declarar o construtor sem argumentos explicitamente.