Atualizado: 26/07/2025

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

Encapsulamento e Modificadores de Acesso em Java

Um dos pilares da Programação Orientada a Objetos é o princípio do Encapsulamento. A ideia central é simples, mas poderosa: proteger os dados de um objeto (seu estado) contra acessos e modificações indevidas, garantindo sua integridade e consistência.

O encapsulamento agrupa os dados e os métodos que operam sobre esses dados dentro de uma única unidade (a classe), e controla o acesso a esses dados. A ferramenta que o Java nos dá para implementar esse controle são os modificadores de acesso.

Modificadores de Acesso: Definindo os Limites

Todo membro de uma classe (campo ou método) possui um modificador de acesso que define sua visibilidade, determinando de quais partes do código ele pode ser acessado.

Java oferece quatro níveis de acesso, do mais restritivo ao mais permissivo:

ModificadorVisibilidadeDescrição
privateApenas na ClasseO membro é acessível somente de dentro da própria classe onde foi declarado. Este é o nível mais restritivo e seguro.
(padrão)Apenas no PacoteSe nenhum modificador for especificado, o acesso é package-private. O membro é visível para qualquer classe no mesmo pacote.
protectedPacote e SubclassesO membro é visível para classes no mesmo pacote e também para subclasses (através de herança), mesmo que elas estejam em pacotes diferentes.
publicEm todo lugarO membro é acessível de qualquer outra classe, em qualquer pacote. É o nível de acesso mais aberto.

Para ilustrar, suponha que as classes Program e Person estão no mesmo pacote:

public class Program {
    public static void main(String[] args) {
        Person kate = new Person("Kate", 32);

        // Acesso a um campo com visibilidade padrão. OK, pois estão no mesmo pacote.
        kate.name = "Katherine";

        // kate.age = 33; // ERRO DE COMPILAÇÃO! O campo 'age' é private.
    }
}

class Person {
    String name;      // Acesso padrão (package-private)
    private int age;  // Acesso privado

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Se Program estivesse em um pacote diferente, ela não poderia acessar nem mesmo o campo name, pois este não é public.

O Encapsulamento na Prática: Protegendo o Estado do Objeto

Poderíamos simplesmente declarar tudo como public para facilitar o acesso, mas essa prática é perigosa. Imagine que o campo age da classe Person fosse público. Qualquer parte do código poderia fazer kate.age = -50;, corrompendo o estado do objeto e violando uma regra de negócio óbvia (idade não pode ser negativa).

O encapsulamento resolve isso. A prática recomendada é:

  1. Declarar todos os campos como private. Isso os "esconde" do mundo exterior.
  2. Fornecer métodos public para interagir com esses campos. Esses métodos atuam como "porteiros" controlados.

Essa abordagem é implementada com os métodos getters e setters:

  • Getter (Accessor): Um método público que e retorna o valor de um campo privado (ex: getAge()).
  • Setter (Mutator): Um método público que modifica o valor de um campo privado, geralmente aplicando alguma lógica de validação (ex: setAge()).

Veja a classe Person reescrita de forma encapsulada e segura:

public class Program {
    public static void main(String[] args) {
        Person kate = new Person("Kate", 30);

        System.out.println(kate.getName() + " tem " + kate.getAge() + " anos."); // Saída: Kate tem 30 anos.

        // Modificando a idade através do "porteiro" (o setter)
        kate.setAge(33);
        System.out.println("Nova idade: " + kate.getAge()); // Saída: Nova idade: 33

        // Tentando atribuir um valor inválido. A regra de negócio no setter vai impedir.
        kate.setAge(120);
        System.out.println("Idade após tentativa inválida: " + kate.getAge()); // Saída: Idade após tentativa inválida: 33
    }
}

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        // É uma boa prática usar os próprios setters no construtor
        // para garantir que a validação seja aplicada desde a criação.
        this.setName(name);
        this.setAge(age);
    }

    // --- Getter para 'name' (permite a leitura do nome) ---
    public String getName() {
        return this.name;
    }

    // --- Setter para 'name' (permite a escrita do nome) ---
    public void setName(String name) {
        this.name = name;
    }

    // --- Getter para 'age' (permite a leitura da idade) ---
    public int getAge() {
        return this.age;
    }

    // --- Setter para 'age' (controla a escrita da idade) ---
    public void setAge(int age) {
        // A classe agora tem total controle sobre seu estado interno.
        if (age > 0 && age < 110) {
            this.age = age;
        }
    }
}

📝 Exercícios

Tarefa 1 (Teoria)

Descrição: Analise a classe Funcionario abaixo. A partir de uma outra classe no mesmo pacote, quais campos de um objeto Funcionario podem ser acessados diretamente?

class Funcionario {
    public String nome;        // Acessível de qualquer lugar
    double salario;          // Acesso padrão (apenas no pacote)
    private String idInterno;  // Acessível apenas dentro da classe Funcionario
}

Alternativas:

  • Apenas o campo nome.
  • Os campos nome e salario.
  • Apenas o campo idInterno.
  • Nenhum dos campos pode ser acessado diretamente.
  • Todos os campos podem ser acessados diretamente.
Resposta

A resposta correta é: Os campos nome e salario.

Explicação:

Vamos analisar a visibilidade de cada campo a partir de uma classe no mesmo pacote:

  • nome: É public, o que significa que ele tem a visibilidade máxima e pode ser acessado de qualquer lugar, incluindo de uma classe no mesmo pacote. (Acesso permitido)
  • salario: Não tem um modificador de acesso explícito, o que significa que ele tem o acesso padrão (package-private). Membros com acesso padrão são visíveis para qualquer outra classe que esteja no mesmo pacote. (Acesso permitido)
  • idInterno: É private, o que significa que ele só pode ser acessado de dentro do código da própria classe Funcionario. Qualquer tentativa de acessá-lo a partir de outra classe, mesmo que no mesmo pacote, resultará em um erro de compilação. (Acesso negado)
  • Portanto, de uma classe no mesmo pacote, apenas os campos nome e salario são diretamente acessíveis.

    Tarefa 2 (Prática)

    Descrição: Na classe Produto, os campos nome e preco foram declarados como private. Crie os métodos get e set públicos para ambos os campos, permitindo que o código no método main funcione corretamente.

    Código inicial:

    public class Main {
        public static void main(String[] args) {
            Produto caneta = new Produto();
    
            caneta.setNome("Caneta Azul");
            caneta.setPreco(1.50);
    
            System.out.println("Produto: " + caneta.getNome());
            System.out.println("Preço: R$" + caneta.getPreco());
        }
    }
    
    class Produto {
        private String nome;
        private double preco;
    
        // Crie os getters e setters aqui
    
    }
    Resposta

    Solução:

    public class Main {
        public static void main(String[] args) {
            Produto caneta = new Produto();
    
            caneta.setNome("Caneta Azul");
            caneta.setPreco(1.50);
    
            System.out.println("Produto: " + caneta.getNome());
            System.out.println("Preço: R$" + caneta.getPreco());
        }
    }
    
    class Produto {
        private String nome;
        private double preco;
    
        // Getter para 'nome'
        public String getNome() {
            return this.nome;
        }
    
        // Setter para 'nome'
        public void setNome(String nome) {
            this.nome = nome;
        }
    
        // Getter para 'preco'
        public double getPreco() {
            return this.preco;
        }
    
        // Setter para 'preco'
        public void setPreco(double preco) {
            this.preco = preco;
        }
    }

    Explicação: Para cada campo private (nome e preco), foram criados dois métodos public.

  • O getter (ex: getNome()) simplesmente retorna o valor do campo privado, permitindo sua leitura.
  • O setter (ex: setNome()) recebe um valor como parâmetro e o atribui ao campo privado, permitindo sua modificação. Essa é a implementação padrão do encapsulamento para controlar o acesso aos dados.
  • 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