Atualizado: 26/07/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Programação Orientada a Objetos: Classes e Objetos em Java

Java é uma linguagem puramente orientada a objetos, o que significa que seus conceitos fundamentais, classe e objeto, são a espinha dorsal de qualquer programa. Uma aplicação Java pode ser vista como um conjunto de objetos que interagem entre si para realizar tarefas.

Classes e Objetos

A maneira mais fácil de entender a diferença entre classe e objeto é com uma analogia:

  • Uma classe é uma planta de uma casa. Ela define todas as características e funcionalidades que a casa terá: número de quartos, cor das paredes, a capacidade de acender luzes, abrir portas, etc. A planta é apenas o modelo, o projeto.
  • Um objeto é a casa construída a partir dessa planta. É uma instância concreta e real que existe na memória. Você pode construir várias casas (vários objetos) a partir da mesma planta (da mesma classe), e cada casa será independente, com suas próprias características (uma pode ser azul, outra vermelha).

Em Java, uma classe é definida com a palavra-chave class:

// A classe Person é a "planta"
class Person {
    // Corpo da classe aqui
}

Todo objeto possui duas características principais:

  • Estado: Os dados que ele armazena. Na classe, o estado é representado por campos (ou atributos/variáveis de instância).
  • Comportamento: As ações que ele pode executar. Na classe, o comportamento é representado por métodos.

Vamos expandir nossa classe Person:

class Person {

    // --- ESTADO (Campos) ---
    String name; // armazena o nome
    int age;     // armazena a idade

    // --- COMPORTAMENTO (Métodos) ---
    void displayInfo() {
        System.out.printf("Name: %s \tAge: %d\n", name, age);
    }
}

Instanciando um Objeto a Partir de uma Classe

Para usar nossa classe, precisamos criar um objeto a partir dela. Este processo é chamado de instanciação.

public class Program {
    public static void main(String[] args) {
        // 1. Declara uma variável de referência do tipo Person
        Person tom;

        // 2. Cria um objeto (instância) da classe Person e atribui sua referência a 'tom'
        tom = new Person();
    }
}

No passo 1, a variável tom é criada, mas seu valor inicial é null, ou seja, ela não aponta para nenhum objeto na memória. No passo 2, o operador new aloca memória para um novo objeto Person, e a referência a essa memória é atribuída à variável tom. Agora tom "sabe" onde encontrar o objeto.

Uma vez que o objeto existe, podemos acessar seus campos e métodos usando o operador . (ponto):

public static void main(String[] args) {
    Person tom = new Person(); // Cria o objeto

    // Acessa e modifica os campos do objeto 'tom'
    tom.name = "Tom";
    tom.age = 34;

    // Chama um método do objeto 'tom'
    tom.displayInfo(); // Name: Tom   Age: 34
}

Nota sobre arquivos: Geralmente, cada classe pública é definida em seu próprio arquivo .java com o mesmo nome. Para simplificar, estamos usando múltiplas classes em um só arquivo.

Construtores: A Inicialização do Objeto

Um construtor é um bloco de código especial, semelhante a um método, que é executado automaticamente no momento em que um objeto é criado (new). Sua principal responsabilidade é inicializar o estado do objeto, garantindo que ele nasça em um estado consistente.

Se você não definir nenhum construtor, o Java fornece um construtor padrão (sem parâmetros) que inicializa os campos com seus valores padrão (0 para números, false para booleanos, null para objetos).

Para maior controle, podemos definir nossos próprios construtores. Uma classe pode ter vários construtores, desde que suas assinaturas (a lista de parâmetros) sejam diferentes. Isso é chamado de sobrecarga de construtores.

public class Program {
    public static void main(String[] args) {
        // Usando o construtor padrão
        Person tom = new Person();
        tom.displayInfo(); // Name: Undefined   Age: 18

        // Usando o construtor com nome
        Person alice = new Person("Alice");
        alice.displayInfo(); // Name: Alice   Age: 18

        // Usando o construtor com nome e idade
        Person bob = new Person("Bob", 25);
        bob.displayInfo(); // Name: Bob   Age: 25
    }
}

class Person {
    String name;
    int age;

    // 1. Construtor padrão (sem parâmetros)
    Person() {
        name = "Undefined";
        age = 18;
    }

    // 2. Construtor que recebe um nome
    Person(String n) {
        name = n;
        age = 18;
    }

    // 3. Construtor que recebe nome e idade
    Person(String n, int a) {
        name = n;
        age = a;
    }

    void displayInfo() {
        System.out.printf("Name: %s \tAge: %d\n", name, age);
    }
}

A Palavra-chave this

A palavra-chave this é uma referência para a instância atual do objeto. Ela é usada principalmente para dois propósitos:

  1. Diferenciar campos de parâmetros: Quando um parâmetro de um construtor ou método tem o mesmo nome de um campo da classe, this é usado para desambiguar e se referir ao campo da instância.
  2. Encadeamento de construtores (Constructor Chaining): Um construtor pode chamar outro construtor da mesma classe para evitar a repetição de código.

Vamos refatorar nossa classe Person usando this para torná-la mais robusta e menos repetitiva:

public class Program {
    public static void main(String[] args) {
        // Usando o construtor padrão
        Person tom = new Person();
        tom.displayInfo(); // Name: Undefined   Age: 18

        // Usando o construtor com nome
        Person alice = new Person("Alice");
        alice.displayInfo(); // Name: Alice   Age: 18

        // Usando o construtor com nome e idade
        Person bob = new Person("Bob", 25);
        bob.displayInfo(); // Name: Bob   Age: 25
    }
}

class Person {
    String name;
    int age;

    // Construtor 1: chama o Construtor 3 com valores padrão
    Person() {
        this("Undefined", 18);
    }

    // Construtor 2: chama o Construtor 3, fornecendo uma idade padrão
    Person(String name) {
        this(name, 18);
    }

    // Construtor 3: o construtor principal, que realiza a inicialização
    Person(String name, int age) {
        // "this.name" se refere ao campo da classe.
        // "name" se refere ao parâmetro do construtor.
        this.name = name;
        this.age = age;
    }

    void displayInfo() {
        System.out.printf("Name: %s \tAge: %d\n", this.name, this.age);
    }
}

Essa abordagem é muito superior, pois centraliza a lógica de atribuição em um único construtor.

Blocos de Inicialização de Instância

Java oferece uma outra forma de inicializar objetos: os blocos de inicialização de instância. É um bloco de código {...} definido diretamente no corpo da classe.

public class Program {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println("Nome: " + person.name + ", Idade: " + person.age); // Nome: Undefined, Idade: 18
    }
}

class Person {
    String name;
    int age;

    // Bloco de inicialização de instância
    {
        System.out.println("Bloco de inicialização executado!");
        name = "Undefined";
        age = 18;
    }

    Person() {
        // Construtor vazio
    }
}

Este bloco é executado toda vez que um objeto é instanciado, e sua execução ocorre antes da execução do construtor.

Quando usar? Eles são úteis para compartilhar uma lógica de inicialização complexa entre múltiplos construtores, especialmente se essa lógica não for uma simples chamada a outro construtor.

Boa Prática: Para inicializações simples, como age = 18;, é mais comum e legível inicializar o campo diretamente em sua declaração: int age = 18;. Blocos de inicialização são reservados para cenários mais complexos.


📝 Exercícios

Tarefa 1 (Teoria)

Descrição: O que será impresso no console ao executar o método main abaixo?

public class Main {
    public static void main(String[] args) {
        Carro meuCarro = null;
        System.out.println(meuCarro.modelo);
    }
}

class Carro {
    String modelo = "Sedan";
}

Alternativas:

  • Sedan
  • null
  • O código não irá compilar.
  • Ocorrerá um NullPointerException em tempo de execução.
  • Nada será impresso.
Resposta

A resposta correta é: Ocorrerá um NullPointerException em tempo de execução.

Explicação: A linha Carro meuCarro = null; declara uma variável de referência meuCarro, mas a instrui explicitamente a não apontar para nenhum objeto (seu valor é null). Na linha seguinte, o código tenta acessar o campo modelo através dessa referência nula. Como não há um objeto real na memória para se obter o campo modelo, o Java lança um NullPointerException ao tentar "desreferenciar" uma variável nula.

Tarefa 2 (Prática)

Descrição: Complete o construtor da classe Livro para que ele inicialize os campos titulo e autor com os valores recebidos como parâmetros.

Código inicial:

public class Main {
    public static void main(String[] args) {
        Livro livroFavorito = new Livro("O Senhor dos Anéis", "J.R.R. Tolkien");
        livroFavorito.exibirInfo(); // Deve imprimir: Título: O Senhor dos Anéis, Autor: J.R.R. Tolkien
    }
}

class Livro {
    String titulo;
    String autor;

    // Complete este construtor
    Livro(String titulo, String autor) {

    }

    void exibirInfo() {
        System.out.println("Título: " + this.titulo + ", Autor: " + this.autor);
    }
}
Resposta

Solução:

public class Main {
    public static void main(String[] args) {
        Livro livroFavorito = new Livro("O Senhor dos Anéis", "J.R.R. Tolkien");
        livroFavorito.exibirInfo(); // Deve imprimir: Título: O Senhor dos Anéis, Autor: J.R.R. Tolkien
    }
}

class Livro {
    String titulo;
    String autor;

    Livro(String titulo, String autor) {
        this.titulo = titulo;
        this.autor = autor;
    }

    void exibirInfo() {
        System.out.println("Título: " + this.titulo + ", Autor: " + this.autor);
    }
}

Explicação: Dentro do construtor, os nomes dos parâmetros (titulo e autor) são os mesmos que os nomes dos campos da classe. Para diferenciar, usamos a palavra-chave this. this.titulo se refere ao campo da instância do objeto, enquanto titulo (sem o this.) se refere ao parâmetro que foi passado para o construtor. A atribuição this.titulo = titulo; armazena o valor do parâmetro no campo correspondente do objeto que está sendo criado.

Tarefa 3 (Prática)

Descrição: Crie um método chamado acelerar() na classe Moto que aumente a velocidade (velocidadeAtual) em 10 a cada vez que for chamado.

Código inicial:

public class Main {
    public static void main(String[] args) {
        Moto minhaMoto = new Moto();
        minhaMoto.exibirVelocidade(); // Deve imprimir: Velocidade: 0 km/h

        minhaMoto.acelerar();
        minhaMoto.exibirVelocidade(); // Deve imprimir: Velocidade: 10 km/h

        minhaMoto.acelerar();
        minhaMoto.acelerar();
        minhaMoto.exibirVelocidade(); // Deve imprimir: Velocidade: 30 km/h
    }
}

class Moto {
    int velocidadeAtual = 0;

    // Crie o método acelerar() aqui


    void exibirVelocidade() {
        System.out.println("Velocidade: " + this.velocidadeAtual + " km/h");
    }
}
Resposta

Solução:

// Método acelerar()
void acelerar() {
    this.velocidadeAtual += 10;
}

Explicação: O método acelerar() modifica o estado do objeto. Ele acessa o campo velocidadeAtual da própria instância (this.velocidadeAtual) e incrementa seu valor em 10. Cada chamada a este método altera o valor armazenado nesse campo específico para aquele objeto, demonstrando como os métodos operam sobre os dados da instância.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com