Modificadores de Acesso em Java
Controle a visibilidade em Java com os modificadores de acesso public, private, protected e package-private (padrão).
Modificadores de acesso determinam quem pode ver e usar uma classe, campo, método ou construtor. Java tem quatro níveis — public, protected, package-private (sem palavra-chave) e private — que vão de "o mundo inteiro" a "apenas esta classe". Escolher o correto é como você estabelece a fronteira entre a interface de um objeto e seus detalhes internos.
Os quatro níveis
Do mais permissivo ao mais restritivo:
| Modificador | Visível a partir de |
|---|---|
public | Em qualquer lugar |
protected | Mesmo pacote ou qualquer subclasse (mesmo em outro pacote) |
| (sem palavra-chave) | Apenas o mesmo pacote — package-private |
private | Apenas a própria classe |
É isso. Não existe "friend", nem "module-internal" neste nível; a visibilidade de módulos é um recurso separado do Java Platform Module System que você geralmente não precisa usar.
public
Um membro public faz parte da API publicada da classe — visível para qualquer código que possa ver a própria classe:
public class Greeter {
public String greet(String name) {
return "Hello, " + name;
}
}
new Greeter().greet("world"); // anyone can call thisUse public para as coisas que você pretende que outro código — mesmo outros projetos — chame. O custo é que, uma vez que algo é público, você assumiu um compromisso com ele; alterar a assinatura quebra todos os chamadores.
private
private restringe um membro à sua classe declarante. Nada de fora pode tocá-lo — nem mesmo uma subclasse:
public class Account {
private int balance; // only Account can read/write
public void deposit(int amount) {
if (amount <= 0) throw new IllegalArgumentException();
balance += amount; // ok — same class
}
}
Account a = new Account();
a.balance = -1; // ERROR — balance is privateEste é o recurso mais utilizado para campos. Ocultar o estado com private é o que faz a validação no deposit ter significado real. O capítulo sobre encapsulamento aprofunda esse padrão.
Package-private (sem palavra-chave)
Omita o modificador completamente e o membro fica visível para tudo no mesmo pacote — mas nada fora dele:
// in package com.shop
class CartHelper { // no public — package-private
static int sum(int[] prices) { ... }
}Outras classes em com.shop podem chamar CartHelper.sum(...); código em com.app nem mesmo sabe que a classe existe. Use isso para utilitários internos que o pacote precisa compartilhar, mas que não fazem parte da API externa do projeto.
Um erro comum: omitir o modificador por esquecimento e depois se surpreender quando a classe pode ser usada em main (também no mesmo pacote durante o aprendizado), mas não em um teste em um pacote diferente.
protected
protected é package-private mais subclasses. Código no mesmo pacote pode usar o membro, e qualquer subclasse — mesmo em um pacote diferente — também pode usá-lo:
public class Shape {
protected double area; // subclasses can read/write
}
public class Circle extends Shape {
Circle(double r) {
this.area = Math.PI * r * r; // ok — subclass access
}
}Este é o modificador a usar quando você quer que subclasses possam se integrar à maquinaria da classe pai, mas não quer que código cliente geral a toque. Na prática, protected aparece bem menos do que public ou private; muitos designers preferem campos private com métodos acessores protected para o mesmo efeito com mais controle.
Onde os modificadores se aplicam
Você pode colocar um modificador em:
- Uma classe em si (
public class Foo). Classes de nível superior só podem serpublicou package-private. Classes internas podem ser qualquer uma das quatro. - Um campo (
private int count). - Um método (
public int get() {...}). - Um construtor (
private Singleton() {...}— veja o padrão singleton).
Você não pode colocar um modificador de acesso em uma variável local ou em um parâmetro de método. Eles têm escopo determinado apenas pelo local onde são declarados.
A regra de "uma classe pública por arquivo"
Um arquivo .java pode declarar várias classes de nível superior, mas no máximo uma delas pode ser public, e o nome dela deve corresponder ao nome do arquivo:
// file: Order.java
public class Order { ... } // ok — matches filename
class OrderHelper { ... } // ok — package-private
public class Customer { ... } // ERROR — second public classA maioria dos projetos mantém uma classe por arquivo de qualquer forma, mas utilitários package-private ao lado de uma classe pública às vezes são úteis.
Escolhendo o modificador certo
Uma regra prática que funciona bem:
- Use
privatepor padrão para campos e métodos auxiliares. publicpara os métodos que você realmente quer que sejam chamados de fora.- Package-private para coisas que precisam ser compartilhadas dentro de um pacote, mas não expostas além dele.
protectedapenas quando você especificamente quer acesso por subclasses também.
É fácil ampliar o acesso depois (private → public); é doloroso restringi-lo sem quebrar chamadores. Comece restrito.
Modificadores não alteram o comportamento
Um modificador de acesso é uma verificação em tempo de compilação. Em tempo de execução, dois campos int iguais se comportam de forma idêntica, independentemente de terem sido declarados public ou private. O modificador existe puramente para impedir que outro código compile contra o membro — para reforçar uma fronteira que você está declarando.
Um exemplo prático
O que vem a seguir
public, protected, private são modificadores de acesso. Java tem outra família — os modificadores sem acesso como static, final, abstract, synchronized — que controlam comportamento em vez de visibilidade. O próximo capítulo, modificadores sem acesso, apresenta esses modificadores.