W3docs

Classes e Objetos em Java

Defina uma classe Java e crie objetos (instâncias) a partir dela — a base do modelo orientado a objetos do Java.

Uma classe é uma definição; um objeto é uma instância dessa definição existindo em tempo de execução. A classe descreve como um cachorro é e o que pode fazer; um objeto é Rex, um cachorro específico que vive na memória enquanto seu programa executa. Tudo abaixo se baseia nessa distinção.

Definindo uma classe

Uma definição de classe fica em seu próprio arquivo .java, com o nome da classe. O corpo contém campos (os dados que cada instância carrega) e métodos (o comportamento que cada instância pode executar).

public class Dog {
  String name;
  int    age;

  void describe() {
    System.out.println(name + ", age " + age);
  }
}

Isso declara um tipo. Ainda não cria nenhum cachorro — exatamente como escrever int não cria um inteiro.

Criando um objeto com new

A palavra-chave new pede à JVM que aloque espaço para uma instância e retorne uma referência para ela:

Dog d = new Dog();

Três coisas acontecem nessa linha:

  1. Alocação. A JVM encontra espaço no heap suficiente para um Dog.
  2. Inicialização padrão. Cada campo recebe um valor padrão — null para objetos, 0 para ints, false para booleans.
  3. Chamada do construtor. O () invoca um construtor. Não escrevemos um, então o Java forneceu um construtor padrão sem argumentos que não faz nada a mais. O próximo capítulo sobre construtores cobre como escrever os seus próprios.

Após isso, d contém uma referência — um valor pequeno que aponta para o objeto no heap. O objeto em si é a coisa maior no heap.

Lendo e escrevendo campos

Você acessa um campo escrevendo <referência>.<campo>:

d.name = "Rex";
d.age  = 3;
System.out.println(d.name);   // Rex

O acesso a campos também é como você chama métodos:

d.describe();    // Rex, age 3

O ponto é o mesmo nos dois casos; se o lado direito é um campo ou um método depende apenas do que vem a seguir.

Referências não são o objeto

Esta é a frase mais importante deste capítulo: uma variável de tipo de classe contém uma referência, não o próprio objeto.

Dog a = new Dog();
a.name = "Rex";

Dog b = a;           // copies the REFERENCE, not the dog
b.name = "Buddy";

System.out.println(a.name);   // Buddy

a e b apontam para o mesmo objeto no heap, então modificá-lo por um é visível pelo outro. Compare com primitivos:

int x = 5;
int y = x;       // copies the value
y = 9;
System.out.println(x);    // still 5

x e y são independentes — primitivos são copiados por valor. O capítulo sobre passagem por valor aprofunda o que isso significa para argumentos de método.

null e NullPointerException

Uma variável de referência pode ser null, significando "não aponta para nenhum objeto":

Dog d = null;
d.describe();    // NullPointerException

null é o que você obtém se nunca atribuiu um objeto, ou se um campo de tipo objeto nunca foi inicializado explicitamente. Desreferenciar null (escrever d.algo quando d == null) lança NullPointerException em tempo de execução. Escrever código que não explode em null é metade do Java prático.

Aviso
NullPointerException é um erro em tempo de execução, não um erro de compilação — o código compila normalmente e só falha quando aquela linha de fato é executada. A correção é garantir que a variável aponte para um objeto real primeiro (d = new Dog();) ou proteger com uma verificação (if (d != null) d.describe();) antes de desreferenciá-la.

Comparando objetos: == vs equals

Para referências, == pergunta "essas duas variáveis apontam para o mesmo objeto?":

Dog a = new Dog();
Dog b = new Dog();
Dog c = a;

System.out.println(a == b);   // false — different objects
System.out.println(a == c);   // true  — same object

Se você quiser comparar o conteúdo de dois objetos, chame um método equals em vez disso — toda classe herda um padrão de Object, mas o padrão apenas faz igualdade de referência. Você sobrescreve equals para significar o que quiser; consulte o capítulo equals & hashCode mais adiante nesta parte.

Um arquivo, muitos objetos

Uma única definição de classe suporta instâncias ilimitadas. Todas compartilham o layout, mas cada uma tem seu próprio estado:

Dog rex   = new Dog();   rex.name   = "Rex";   rex.age   = 3;
Dog molly = new Dog();   molly.name = "Molly"; molly.age = 7;

rex.describe();     // Rex, age 3
molly.describe();   // Molly, age 7

Um método como describe lê de this — o objeto no qual foi chamado — portanto o mesmo código imprime saídas diferentes dependendo de qual instância você o chama.

Onde as classes ficam

Um arquivo .java que declara public class Dog deve se chamar Dog.java. Você pode ter classes não públicas no mesmo arquivo, mas apenas uma classe public por arquivo, e seu nome deve corresponder ao nome do arquivo. Para programas pequenos neste capítulo, frequentemente colocaremos classes auxiliares dentro do mesmo arquivo que main usando classes aninhadas static, apenas para manter o exemplo em um único arquivo.

Um exemplo completo

java— editable, runs on the server

O que vem a seguir

Você pode declarar uma classe e instanciá-la, mas até agora o único campo que escreveu foi "qualquer valor serve." O próximo capítulo sobre atributos de classe percorre os campos adequadamente — declaração, padrões, escopo de instância versus classe, e as convenções que o código Java segue.

Prática

Prática
Dado Dog a = new Dog(); Dog b = a; b.name = 'Rex'; — o que System.out.println(a.name) imprime?
Dado Dog a = new Dog(); Dog b = a; b.name = 'Rex'; — o que System.out.println(a.name) imprime?
Was this page helpful?