CodeGym /Cursos /JAVA 25 SELF /Modificadores de acesso

Modificadores de acesso

JAVA 25 SELF
Nível 15, Lição 1
Disponível

1. Visão geral dos modificadores de acesso

Em Java há quatro níveis de acesso para classes, campos, métodos e construtores:

Modificador Onde é acessível?
public
Em qualquer lugar: dentro da classe, em outras classes, em outros pacotes
protected
Dentro da classe, em subclasses (herdeiras), em outras classes do mesmo pacote
(package-private)
Somente dentro do pacote (quando o modificador não é especificado explicitamente)
private
Somente dentro da classe atual

Vamos analisar cada um em mais detalhes — com exemplos, piadas e reviravoltas inesperadas.

public — acesso público

public — é como um aviso para o mundo inteiro: “Entrada liberada para todos!”. Se uma classe, campo, método ou construtor é declarado como public, ele pode ser acessado a partir de qualquer outra classe, até mesmo de outro pacote.

Exemplo:

public class Cat {
    public String name;
    public void sayMeow() {
        System.out.println("Miau!");
    }
}

Esta classe e seus campos/métodos podem ser acessados de qualquer lugar. Isso é conveniente se você quer que sua classe esteja disponível para todos: por exemplo, se estiver escrevendo uma biblioteca.

Mas! Campos públicos nem sempre são uma boa ideia (veja a aula anterior). Normalmente, apenas os métodos que devem ser acessíveis de fora são public, enquanto os campos quase sempre permanecem private.

private — acesso apenas dentro da classe

private — é como um cofre com combinação: ninguém além da própria classe pode acessar esses membros. Nem mesmo as subclasses veem campos e métodos privados!

Exemplo:

public class Cat {
    private String secretName;

    public void setSecretName(String name) {
        secretName = name;
    }

    public String getSecretName() {
        return secretName;
    }
}

Aqui, secretName não pode ser lido ou alterado diretamente a partir de outra classe. Apenas a própria Cat pode fazer isso (ou seus métodos). Isso é a base do encapsulamento: escondemos os detalhes internos e fornecemos acesso a eles apenas por meio de métodos.

protected — acesso protegido

protected — é como um passe VIP: o acesso é permitido à classe, às suas subclasses (mesmo se estiverem em outros pacotes) e a todas as classes dentro do pacote atual.

Exemplo:

public class Animal {
    protected int age;

    protected void growOlder() {
        age++;
    }
}

Agora qualquer classe que herde de Animal poderá acessar o campo age e o método growOlder().

public class Cat extends Animal {
    public void haveBirthday() {
        growOlder();
        System.out.println("O gato completou " + age + " anos!");
    }
}

Além disso, todas as classes dentro do mesmo pacote têm acesso aos membros protected.

(package-private) — acesso dentro do pacote

Se você não especificar nenhum modificador de acesso, o membro da classe é considerado package-private (ou “acesso padrão”). É como uma porta sem tranca, mas apenas para os de casa: o acesso é permitido apenas às classes do mesmo pacote.

Exemplo:

class Dog {
    String name; // package-private
    void bark() { // package-private
        System.out.println("Au!");
    }
}

A classe Dog, seu campo name e o método bark() estão acessíveis apenas dentro do mesmo pacote. Tentar acessá-los de outro pacote causará um erro de compilação.

2. Aplicando modificadores a campos e métodos

Por que os campos quase sempre são private

Os campos de uma classe representam seu estado interno. Se você os deixar públicos, qualquer código externo poderá modificá-los a qualquer momento. É como permitir que crianças desconhecidas brinquem com seus móveis como se fossem Lego: um dia você acorda e a geladeira está virada de ponta-cabeça no banheiro.

Exemplo de encapsulamento ruim:

public class Person {
    public String name;
    public int age;
}

Exemplo de bom encapsulamento:

public class Person {
    private String name;
    private int age;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Métodos (getters e setters) permitem controlar como as classes externas podem alterar os campos. Por exemplo, você pode proibir idade negativa.

Quando tornar métodos public, protected ou package-private

  • public — quando o método deve estar acessível a todos. Geralmente é a funcionalidade principal da classe.
  • protected — quando o método é necessário apenas para subclasses ou dentro do pacote (por exemplo, métodos auxiliares que podem ser úteis em classes filhas).
  • package-private — quando o método é necessário apenas dentro do pacote e não deve ficar acessível externamente (por exemplo, detalhes internos de implementação).
  • private — quando o método é usado apenas dentro da própria classe (por exemplo, métodos auxiliares para a lógica interna).

Exemplo:

public class BankAccount {
    private double balance;

    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
        }
    }

    protected void applyInterest() {
        balance *= 1.05;
    }

    void internalAudit() {
        // package-private: apenas para classes dentro do pacote
    }

    private void logAction(String action) {
        // apenas para necessidades internas da classe
    }
}

3. Exemplos de código: classe com diferentes níveis de acesso

Vamos criar uma classe que tenha de tudo: membros públicos, privados, protegidos e de pacote. Ao mesmo tempo, vamos tentar acessá-los a partir de outras classes e ver o que acontece.

package zoo;

public class Animal {
    public String publicName = "Disponível para todos";
    protected String protectedName = "Somente para herdeiros e para o pacote";
    String packageName = "Somente para o pacote";
    private String privateName = "Somente para Animal";

    public void publicMethod() {
        System.out.println("Método público");
    }

    protected void protectedMethod() {
        System.out.println("Método protegido");
    }

    void packageMethod() {
        System.out.println("Método de pacote");
    }

    private void privateMethod() {
        System.out.println("Método privado");
    }
}

Agora vamos tentar acessar esses membros a partir de outra classe no mesmo pacote:

package zoo;

public class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName);   // OK
        System.out.println(animal.packageName);     // OK
        System.out.println(animal.privateName);  // Erro: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                   // OK
        animal.packageMethod();                     // OK
        animal.privateMethod();                  // Erro: private
    }
}

Agora vamos tentar acessar esses membros a partir de outro pacote:

package other;

import zoo.Animal;

public class Test {
    public static void main(String[] args) {
        Animal animal = new Animal();
        System.out.println(animal.publicName);      // OK
        System.out.println(animal.protectedName); // Erro: protected
        System.out.println(animal.packageName);   // Erro: package-private
        System.out.println(animal.privateName);   // Erro: private
        animal.publicMethod();                      // OK
        animal.protectedMethod();                // Erro: protected
        animal.packageMethod();                  // Erro: package-private
        animal.privateMethod();                  // Erro: private
    }
}

Conclusão:

  • public — acessível em qualquer lugar.
  • protected — acessível dentro do pacote e em subclasses (inclusive de outros pacotes, se via herança).
  • package-private — somente dentro do pacote.
  • private — somente dentro da classe.

4. Boas práticas: como escolher o modificador de acesso

Minimize a visibilidade

Quanto menos código puder ver seu campo ou método, melhor. Exponha apenas o que for realmente necessário ao código externo. Isso é chamado de princípio do menor privilégio (principle of least privilege).

  • Campos quase sempre devem ser private. Exceções — apenas para constantes reais (public static final), mas falaremos mais sobre isso nas próximas aulas.
  • Métodos são public apenas se fizerem parte da interface externa da classe.
  • Métodos auxiliares (lógica interna) — private.
  • Métodos para herdeiros — protected.
  • Métodos de serviço internos do pacote — package-private.

Por que isso é importante?

  • Qualquer mudança nos detalhes de implementação pode quebrar o código de terceiros se esses detalhes estiverem expostos.
  • A classe se torna mais difícil de testar e manter.
  • Erros acidentais (por exemplo, modificar um campo indevidamente) podem levar a bugs.

Às vezes iniciantes pensam: “Pra que essa complicação toda? Deixa tudo public!” Mas depois, quando o projeto cresce, é preciso reescrever metade do programa só porque alguém mudava os campos da classe diretamente.

5. Erros comuns ao trabalhar com modificadores de acesso

Erro nº 1: Deixar campos public ou package-private por padrão.
Se você não especificar um modificador, o campo ou método ficará acessível a todas as classes dentro do pacote. Isso pode levar a situações inesperadas se alguém começar a alterar seus campos diretamente.

Erro nº 2: Tentar acessar um membro private a partir de outra classe.
O compilador não permitirá — você terá um erro. Mas se você resolver contornar isso via reflection (reflexão) — bem-vindo ao mundo de bugs e quedas inesperadas.

Erro nº 3: Public demais.
Se você declarar tudo como public, a classe fica parecida com uma caixa aberta cheia de fios — qualquer um pode puxar o fio errado e quebrar tudo.

Erro nº 4: Não usar protected para métodos necessários apenas às subclasses.
Se um método é necessário apenas para extensão em classes filhas, declare-o protected, e não public.

Erro nº 5: Visibilidade package-private implícita.
Às vezes esquecemos de especificar o modificador, e o método fica acessível a todo o pacote. Isso pode ser uma surpresa se você achava que ele era private.

1
Tarefa
JAVA 25 SELF, nível 15, lição 1
Bloqueado
Lendo o nome no cartão digital 🃏
Lendo o nome no cartão digital 🃏
1
Tarefa
JAVA 25 SELF, nível 15, lição 1
Bloqueado
Calculadora mágica com mecanismo secreto ➕
Calculadora mágica com mecanismo secreto ➕
1
Tarefa
JAVA 25 SELF, nível 15, lição 1
Bloqueado
Assistência interna na equipe de desenvolvimento 🤝
Assistência interna na equipe de desenvolvimento 🤝
1
Tarefa
JAVA 25 SELF, nível 15, lição 1
Bloqueado
Gerenciamento da biblioteca digital: quem pode fazer o quê 🏛️
Gerenciamento da biblioteca digital: quem pode fazer o quê 🏛️
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION