Qual é a diferença entre public, protected, package-private e private em Java?

3171

Em Java, existem regras claras sobre quando usar cada um dos modificadores de acesso, ou seja, o padrão (pacote privada), public, protectede private, ao fazer classe interfacee lidar com a herança?

intrepion
fonte
161
privateoculta outras classes dentro do pacote. publicexpõe a classes fora do pacote. protectedé uma versão publicrestrita apenas a subclasses.
Museful
87
@Tennenrishin - Não; Ao contrário do C ++, em Java, protectedo método também é acessível a partir de todo o pacote. Essa estupidez no modelo de visibilidade de Java quebra o objetivo de protected.
Nicolas Barbulesco
35
@ Nicolas É acessível a partir de todo o pacote, com ou sem protected. Como um modificador de acesso , tudo o que protectedfaz é expor a subclasses fora do pacote.
Museful
15
@tennenrishin - bem, foi o que Nicolas disse ... e você está repetindo agora. O que você disse originalmente foi que protected- e cito - 'é uma versão do público restrita apenas às subclasses', o que não é verdade por sua própria admissão, já que o protected também permite o acesso através de todo o pacote (portanto, não restringe o acesso às subclasses. )
luis.espinal
10
Também concordo com Nicolas em que o modo de acesso protegido em Java é idiota. O que aconteceu foi que o Java conflitou qualificadores de restrição de acesso horizontal (treliça) e vertical. O escopo padrão é uma restrição horizontal / de rede, com a rede sendo o pacote. Público é outra restrição horizontal em que a treliça é o mundo inteiro. Privado e (C ++) protegido são verticais. Teria sido melhor se tivéssemos um acesso cruzado, por exemplo, protected-packagepara os raros casos em que realmente precisávamos, deixando o protectedequivalente à versão C ++ do protected.
Luis.espinal

Respostas:

5639

O tutorial oficial pode ser útil para você.

______________________________________________________________
| │ Classe │ Pacote │ Subclasse │ Subclasse │ Mundo |
| │ │ same (mesmo pacote) │ (pacote diferenciado) │ |
| ──────────┼────────────────┼────────────────────────── ──┼──────── |
| public │ + │ + │ + │ + │ + | 
| ──────────┼────────────────┼────────────────────────── ──┼──────── |
| protegido │ + │ + │ + │ + │ | 
| ──────────┼────────────────┼────────────────────────── ──┼──────── |
| sem modificador│ + │ + │ + │ │ | 
| ──────────┼────────────────┼────────────────────────── ──┼──────── |
| private │ + │ │ │ │ |
| ___________ | _______ | _________ | __________ | __________ | ________ |
 +: acessível em branco: não acessível
David Segonds
fonte
5
A tabela acima está incorreta, pois mesmo os privatemembros podem ser vistos / usados ​​por qualquer classe / método estático no mesmo arquivo de origem.
Usagi Miyamoto
5
O membro protegido pode ser acessado apenas da subclasse do mesmo pacote, mas não da subclasse de pacote diferente. Deve haver uma correção na tabela acima
niks
2
O mundo está dentro do seu projeto . Eu deveria explicar mais. As bibliotecas estão dentro do seu projeto e, se você estiver criando uma biblioteca, elas também exporão essas classes e métodos públicos. Então, dizer apenas dentro do seu projeto é um pouco complicado. "Tudo o que usa" é uma descrição melhor.
Adprocas
3
Por exemplo, se eu tiver MyClasse estiver fazendo AnotherClass extends MyClass, terei acesso a todos os métodos e propriedades protegidos e públicos a partir de dentro AnotherClass. Se o fizer MyClass myClass = new MyClass();em AnotherClassalgum lugar - digamos o construtor - só terei acesso aos métodos públicos se ele estiver em um pacote diferente. Observe que, se eu fizer = new MyClass() { @Override protected void protectedMethod() { //some logic } };, parece que posso acessar métodos protegidos, mas esse é o mesmo que estendê-lo, mas em vez disso, em linha.
Adprocas 04/04
3
Infelizmente, esta resposta é uma simplificação grosseira. A realidade é um pouco mais complicada, especialmente quando você considera protected(o que é realmente um modificador de acesso bastante difícil de entender - a maioria das pessoas que pensam que sabem o que protectedrealmente não sabem ). Além disso, como Bohemian apontou, ele não responde à pergunta - não diz nada sobre quando usar cada modificador de acesso. Na minha opinião, essa resposta não é ruim o suficiente para diminuir o voto, mas fechar. Mas mais de 4000 votos positivos? Como isso aconteceu?
Dawood ibn Kareem
483

(Advertência: eu não sou programador Java, sou programador Perl. O Perl não possui proteções formais, talvez por isso eu entendo o problema tão bem :))

Privado

Como você pensaria, apenas a classe em que é declarada pode vê-lo.

Pacote Privado

Ele só pode ser visto e usado pelo pacote em que foi declarado. Este é o padrão em Java (que alguns vêem como um erro).

Protegido

O Package Private + pode ser visto por subclasses ou membros do pacote.

Público

Todo mundo pode ver.

Publicados

Visível fora do código que eu controlo. (Embora não seja sintaxe do Java, é importante para esta discussão).

O C ++ define um nível adicional chamado "amigo" e, quanto menos você souber sobre isso, melhor.

Quando você deve usar o quê? A idéia toda é encapsulamento para ocultar informações. Na medida do possível, você deseja ocultar os detalhes de como algo é feito por seus usuários. Por quê? Porque então você pode alterá-los mais tarde e não quebrar o código de ninguém. Isso permite otimizar, refatorar, reprojetar e corrigir bugs sem se preocupar com o fato de alguém estar usando o código que você acabou de revisar.

Portanto, a regra geral é tornar as coisas tão visíveis quanto elas precisam ser. Comece com privado e adicione mais visibilidade, conforme necessário. Torne público apenas o que é absolutamente necessário para o usuário saber, todos os detalhes que você tornar públicos reduzem sua capacidade de redesenhar o sistema.

Se você deseja que os usuários possam personalizar comportamentos, em vez de tornar públicos internos para que eles possam substituí-los, geralmente é uma boa ideia colocar essas tripas em um objeto e tornar pública a interface. Dessa forma, eles podem simplesmente conectar um novo objeto. Por exemplo, se você estivesse gravando um CD player e desejasse que o "vá encontrar informações sobre este CD" fosse personalizável, em vez de tornar esses métodos públicos, você colocaria toda essa funcionalidade em seu próprio objeto e tornaria público o getter / setter do seu objeto . Dessa maneira, ser mesquinho ao expor suas entranhas incentiva uma boa composição e separação de preocupações

Pessoalmente, fico com apenas "privado" e "público". Muitos idiomas OO simplesmente têm isso. "Protegido" pode ser útil, mas é realmente uma trapaça. Uma vez que uma interface é mais que privada, ela está fora de seu controle e você precisa procurar no código de outras pessoas para encontrar usos.

É aqui que entra a idéia de "publicado". Alterar uma interface (refatorá-la) exige que você encontre todo o código que a está usando e mude também. Se a interface for privada, não há problema. Se estiver protegido, você precisa encontrar todas as suas subclasses. Se for público, você precisa encontrar todo o código que usa seu código. Às vezes, isso é possível, por exemplo, se você estiver trabalhando em código corporativo apenas para uso interno, não importa se a interface é pública. Você pode pegar todo o código do repositório corporativo. Mas se uma interface for "publicada", se houver código usando-a fora do seu controle, você será processado. Você deve suportar essa interface ou correr o risco de quebrar o código. Até interfaces protegidas podem ser consideradas publicadas (e é por isso que eu não

Muitos idiomas consideram a natureza hierárquica de público / protegido / privado muito limitadora e não alinhada com a realidade. Para esse fim, existe o conceito de uma classe de características , mas esse é outro programa.

Schwern
fonte
26
friends -> "Quanto menos você souber, melhor" ---> Dá visibilidade seletiva, que ainda é superior à privacidade dos pacotes. No C ++, ele tem seus usos, porque nem todas as funções podem ser funções de membro e amigos é melhor do que publicar. É claro que existe o perigo de uso indevido por mentes más.
Sebastian Mach
30
Também deve ser observado que "protegido" em C ++ tem um significado diferente - um método protegido é efetivamente privado, mas ainda pode ser chamado de uma classe herdada. (Ao contrário de Java, onde ele pode ser chamado por qualquer classe dentro do mesmo pacote.)
Rhys van der Waerden
9
@RhysvanderWaerden C # é o mesmo que C ++ nesse aspecto. Acho bastante estranho que o Java não permita declarar um membro acessível à subclasse, mas não o pacote inteiro. É meio que de cabeça para mim - um pacote é de escopo mais amplo que uma classe infantil!
Konrad Morawski
15
O pacote IMHO do @KonradMorawski tem escopo menor que a subclasse. Se você não declarou sua classe como final, os usuários devem poder subclassificá-la - portanto, o java protegido faz parte da sua interface publicada. OTOH, pacotes são implicitamente desenvolvidos por uma única organização: por exemplo, com.mycompany.mypackage. Se o seu código se declarar no meu pacote, você se declara implicitamente como parte da minha organização, por isso devemos nos comunicar. Assim, o pacote publica para um público menor / mais fácil de alcançar (pessoas da minha empresa) do que subclasse (pessoas que estendem meu objeto) e, portanto, conta como menor visibilidade.
Eponymous
2
friendé bom para definir relacionamentos especiais entre classes. Permite encapsulamento superior em muitos casos, quando usado corretamente. Por exemplo, ele pode ser usado por uma classe privilegiada de fábrica para injetar dependências internas em um tipo construído. Ele tem um nome ruim porque as pessoas que não se preocupam em manter corretamente um modelo de objeto bem projetado podem abusar dele para facilitar sua carga de trabalho.
Dennis
434

Aqui está uma versão melhor da tabela, que também inclui uma coluna para módulos.

Modificadores de acesso Java

Explicações

  • Um membro privado ( i) é acessível apenas na mesma classe em que é declarado.

  • Um membro sem modificador de acesso ( j) é acessível apenas dentro das classes no mesmo pacote.

  • Um membro protegido ( k) é acessível em todas as classes no mesmo pacote e nas subclasses de outros pacotes.

  • Um membro público ( l) é acessível a todas as classes (a menos que resida em um módulo que não exporta o pacote no qual está declarado).


Qual modificador escolher?

Os modificadores de acesso são uma ferramenta para ajudá-lo a impedir a quebra acidental do encapsulamento (*) . Pergunte a si mesmo se você pretende que o membro seja algo interno à classe, pacote, hierarquia de classes ou que não seja totalmente interno e escolha o nível de acesso de acordo.

Exemplos:

  • Um campo long internalCounterprovavelmente deve ser privado, pois é mutável e um detalhe de implementação.
  • Uma classe que só deve ser instanciada em uma classe de fábrica (no mesmo pacote) deve ter um construtor restrito, pois não deve ser possível chamá-lo diretamente de fora do pacote.
  • Um void beforeRender()método interno chamado logo antes da renderização e usado como um gancho nas subclasses deve ser protegido.
  • Um void saveGame(File dst)método chamado do código da GUI deve ser público.

(*) O que é exatamente o encapsulamento?

aioobe
fonte
11
Apenas dizendo: há muitas pessoas que têm problemas para distinguir a coloração vermelho / verde. Tabelas usando vermelho / verde (laranja / ou amarelo / ...) esquemas de cores raramente são "melhor" em qualquer coisa ;-)
GhostCat
1
@GhostCat, eu discordo. Eu acho que vermelho / verde se alinha intuitivamente com "funciona" / "não funciona" para muitas pessoas, ou seja, é melhor do que muitas alternativas.
aioobe
8
colourblindawareness.org/colour-blindness/… ... Os 8% dos daltônicos podem ser divididos aproximadamente em 1% deuteranopes, 1% protanopes, 1% protanomalous e 5% deuteranomalous . E como eu sou um desses 50% desses 5%, tenha certeza: vermelho / verde é uma merda.
GhostCat 14/11/19
6
@ GhostCat Ok .. essa é uma parte maior da população do que eu esperava. Carreguei a imagem neste simulador de daltonismo e testei todos os modos diferentes. Mesmo no modo monocromático / acromatopsia, a diferença de cor é razoável. Você consegue ver a diferença ou o simulador está desligado? (Eu ainda sou da opinião que o vermelho / verde é muito intuitiva para cor ver as pessoas.)
aioobe
3
Percebo a diferença, mas também consigo passar metade dos testes de daltonismo que temos que fazer na Alemanha para obter a carteira de motorista ;-) ... mas acho que esse simulador é "bom o suficiente".
GhostCat
206
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |     
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
private         |              |          |              |       
____________________________________________________________________
Abdull
fonte
1
Vale a pena colocar em palavras - "O modificador protegido torna o objeto disponível em outros pacotes, enquanto o padrão / no-modifier restringe o acesso ao mesmo pacote"
vanguard69
2
@ vanguard69, o protectedmodificador torna a coisa marcada (classe, método ou campo) disponível para alguma outra classe em outro pacote somente se a outra classe for uma subclasse da classe onde a coisaprotected marcada é declarada.
Abdull
"não submetido"? "esta subclasse em outro pacote"? Hã. Eu pensei que sabia Java.
sehe
@AlexanderFarber você otimizou para uma configuração de navegador específica? Este é o meu chrome agora e este é o Firefox #
10/17
Hmm, vamos reverter minha alteração então #
Alexander Farber
165

Regra fácil. Comece declarando tudo como privado. E, em seguida, progredir em direção ao público à medida que as necessidades surgirem e o design o justificar.

Ao expor os membros, pergunte a si mesmo se você está expondo opções de representação ou abstração. O primeiro é algo que você deseja evitar, pois introduzirá muitas dependências na representação real, e não em seu comportamento observável.

Como regra geral, tento evitar a substituição de implementações de métodos por subclassificação; é muito fácil estragar a lógica. Declare métodos protegidos abstratos se você pretende que ele seja substituído.

Além disso, use a anotação @Override ao substituir para impedir que as coisas quebrem ao refatorar.

John Nilsson
fonte
3
@RuchirBaronia, "world" = todo o código do aplicativo, independentemente de onde estiver.
Andrejs 26/02
116

Na verdade, é um pouco mais complicado do que mostra uma grade simples. A grade informa se um acesso é permitido, mas o que exatamente constitui um acesso? Além disso, os níveis de acesso interagem com classes e herança aninhadas de maneiras complexas.

O acesso "padrão" (especificado pela ausência de uma palavra-chave) também é chamado de pacote privado . Exceção: em uma interface, nenhum modificador significa acesso público; modificadores que não sejam públicos são proibidos. As constantes enum são sempre públicas.

Sumário

É permitido um acesso a um membro com este especificador de acesso?

  • Membro é private : Somente se membro estiver definido na mesma classe que o código de chamada.
  • O membro é privado do pacote: somente se o código de chamada estiver dentro do pacote que o encerra imediatamente.
  • Membro é protected : Mesmo pacote, ou se member for definido em uma superclasse da classe que contém o código de chamada.
  • Membro é public: Sim.

A que especificadores de acesso se aplicam

Variáveis ​​locais e parâmetros formais não podem receber especificadores de acesso. Como eles são inerentemente inacessíveis para o exterior de acordo com as regras de escopo, eles são efetivamente privados.

Para classes no escopo superior, somente publice package-private são permitidos. Essa opção de design é presumivelmente porque protectede privateseria redundante no nível do pacote (não há herança de pacotes).

Todos os especificadores de acesso são possíveis nos membros da classe (construtores, métodos e funções estáticas dos membros, classes aninhadas).

Relacionado: Acessibilidade de classe Java

Ordem

Os especificadores de acesso podem ser pedidos estritamente

público> protegido> pacote privado> privado

significando que publicfornece o máximo de acesso, privateo mínimo. Qualquer referência possível a um membro privado também é válida para um membro privado do pacote; qualquer referência a um membro privado do pacote é válida em um membro protegido e assim por diante. (Conceder acesso a membros protegidos a outras classes no mesmo pacote foi considerado um erro.)

Notas

  • Os métodos de uma classe têm permissão para acessar membros particulares de outros objetos da mesma classe. Mais precisamente, um método da classe C pode acessar membros privados de C em objetos de qualquer subclasse de C. Java não suporta a restrição de acesso por instância, apenas por classe. (Compare com o Scala, que o suporta usando private[this].)
  • Você precisa acessar um construtor para construir um objeto. Portanto, se todos os construtores forem privados, a classe poderá ser construída apenas pelo código que vive dentro da classe (normalmente métodos de fábrica estáticos ou inicializadores de variáveis ​​estáticas). Da mesma forma para construtores privados ou protegidos por pacotes.
    • Somente ter construtores privados também significa que a classe não pode ser subclassificada externamente, pois o Java exige que os construtores de uma subclasse chamem implícita ou explicitamente um construtor de superclasse. (No entanto, ele pode conter uma classe aninhada que a subclasse.)

Classes internas

Você também deve considerar escopos aninhados , como classes internas. Um exemplo da complexidade é que as classes internas têm membros, os quais podem usar modificadores de acesso. Então você pode ter uma classe interna privada com um membro público; o membro pode ser acessado? (Veja abaixo.) A regra geral é examinar o escopo e pensar recursivamente para ver se você pode acessar cada nível.

No entanto, isso é bastante complicado e, para obter detalhes completos, consulte a Java Language Specification . (Sim, houve erros do compilador no passado.)

Para uma amostra de como eles interagem, considere este exemplo. É possível "vazar" classes internas privadas; isso geralmente é um aviso:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Saída do compilador:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Algumas questões relacionadas:

Caracol mecânico
fonte
1
"modificadores que não sejam públicos são proibidos" - a partir do Java 9, esse não é mais o caso: as interfaces também podem ter métodos privados.
MC Emperor
96

Como um princípio básico:

  • private: escopo da classe.
  • default(ou package-private): escopo do pacote.
  • protected: package scope + child(como pacote, mas podemos subclassificá-lo de pacotes diferentes). O modificador protegido sempre mantém o relacionamento "pai-filho".
  • public: em toda parte.

Como resultado, se dividirmos o direito de acesso em três direitos:

  • (D) irect (invocar a partir de um método dentro da mesma classe ou através da sintaxe "this").
  • (R) eference (invoque um método usando uma referência à classe ou através da sintaxe "ponto").
  • (I) herança (via subclasse).

então temos esta tabela simples:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+
nxhoaf
fonte
54

Em muito curto

  • public: acessível de qualquer lugar.
  • protected: acessível pelas classes do mesmo pacote e pelas subclasses residentes em qualquer pacote.
  • padrão (nenhum modificador especificado): acessível pelas classes do mesmo pacote.
  • private: acessível somente na mesma classe.
Ravi
fonte
48

O modificador de acesso mais incompreendido em Java é protected. Sabemos que é semelhante ao modificador padrão, com uma exceção na qual as subclasses podem vê-lo. Mas como? Aqui está um exemplo que espero esclarecer a confusão:

  • Suponha que temos 2 classes; Fathere Son, cada um em seu próprio pacote:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
  • Vamos adicionar um método protegido foo()para Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
  • O método foo()pode ser chamado em 4 contextos:

    1. Dentro de uma classe que está localizada no mesmo pacote em que foo()está definido ( fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
    2. Dentro de uma subclasse, na instância atual, via thisou super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. Em uma referência cujo tipo é da mesma classe:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
    4. Em uma referência cujo tipo é a classe pai e está dentro do pacote em que foo()está definido ( fatherpackage) [Isso pode ser incluído no contexto no. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
  • As seguintes situações não são válidas.

    1. Em uma referência cujo tipo é a classe pai e está fora do pacote em que foo()está definido ( fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
    2. Uma não subclasse dentro de um pacote de uma subclasse (uma subclasse herda os membros protegidos de seu pai e os torna privados para não subclasses):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }
Eng.Fouad
fonte
Object#clone()é um exemplo de um protectedmembro.
Eng.Fouad
Qual é a diferença entre doing super.foo()e a primeira situação inválida f.foo()?
cst1992
1
@ cst1992 É confuso, mas consulte a Especificação da Linguagem Java 6.6.2: "Um membro ou construtor protegido de um objeto pode ser acessado de fora do pacote no qual é declarado apenas pelo código responsável pela implementação desse objeto". Com super.foo () a referência "super" é "diretamente responsável pela implementação", mas a referência "f" não é. Por quê? Porque você pode estar 100% certo de que "super" é do tipo Pai, mas não para "f"; em tempo de execução, poderia ser algum outro subtipo de pai. Veja docs.oracle.com/javase/specs/jls/se9/html/…
skomisa
1
É refrescante ler uma resposta de alguém que entende protected. Infelizmente, todas as outras respostas nesta página que definem protectedentendem um pouco errado.
Dawood ibn Kareem
30

Privado

  • Métodos, Variáveis ​​e Construtores

Métodos, variáveis ​​e construtores declarados privados só podem ser acessados ​​dentro da própria classe declarada.

  • Classe e interface

Modificador de acesso privado é o nível de acesso mais restritivo. Classe e interfaces não podem ser particulares.

Nota

Variáveis ​​declaradas privadas podem ser acessadas fora da classe se métodos públicos getter estiverem presentes na classe. Variáveis, métodos e construtores declarados protegidos em uma superclasse podem ser acessados ​​apenas pelas subclasses de outro pacote ou qualquer classe dentro do pacote da classe dos membros protegidos.


Protegido

  • Classe e interface

O modificador de acesso protegido não pode ser aplicado à classe e interfaces.

Métodos, campos podem ser declarados protegidos, no entanto, métodos e campos em uma interface não podem ser declarados protegidos.

Nota

O acesso protegido oferece à subclasse a chance de usar o método ou variável auxiliar, enquanto impede que uma classe não relacionada tente usá-lo.


Público

Uma classe, método, construtor, interface etc declarada pública pode ser acessada de qualquer outra classe.

Portanto, campos, métodos, blocos declarados dentro de uma classe pública podem ser acessados ​​a partir de qualquer classe pertencente ao Universo Java.

  • Pacotes Diferentes

No entanto, se a classe pública que estamos tentando acessar estiver em um pacote diferente, ela ainda precisará ser importada.

Por causa da herança de classe, todos os métodos e variáveis ​​públicos de uma classe são herdados por suas subclasses.


Padrão - Nenhuma palavra-chave:

Modificador de acesso padrão significa que não declaramos explicitamente um modificador de acesso para uma classe, campo, método etc.

  • Dentro dos mesmos pacotes

Uma variável ou método declarado sem nenhum modificador de controle de acesso está disponível para qualquer outra classe no mesmo pacote. Os campos em uma interface são implicitamente públicos como estáticos finais e os métodos em uma interface são por padrão públicos.

Nota

Não podemos substituir os campos estáticos. Se você tentar substituí-lo, ele não mostrará nenhum erro, mas não funcionará como nós, exceto.

Respostas relacionadas

Links de referências

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm

Nambi
fonte
21

A diferença pode ser encontrada nos links já fornecidos, mas qual deles usar normalmente se resume ao "Princípio do Menos Conhecimento". Permita apenas a menor visibilidade necessária.

Joe Phillips
fonte
20

Privado : acesso limitado apenas à aula

Padrão (sem modificador) : acesso limitado à classe e pacote

Protegido : acesso limitado a classe, pacote e subclasses (dentro e fora do pacote)

Público : acessível a classe, pacote (todos) e subclasses ... Em resumo, em qualquer lugar.

samkit shah
fonte
17

Modificadores de acesso existem para restringir o acesso em vários níveis.

Público: É basicamente tão simples quanto você pode acessar de qualquer classe, esteja no mesmo pacote ou não.

Para acessar se você estiver no mesmo pacote, poderá acessar diretamente, mas se estiver em outro pacote, poderá criar um objeto da classe.

Padrão: está acessível no mesmo pacote a partir de qualquer classe de pacote.

Para acessar, você pode criar um objeto da classe. Mas você não pode acessar essa variável fora do pacote.

Protegido: você pode acessar variáveis ​​no mesmo pacote e subclasse em qualquer outro pacote. então, basicamente, é o padrão + comportamento herdado .

Para acessar o campo protegido definido na classe base, você pode criar o objeto da classe filho.

Privado: pode ser acessado na mesma classe.

Nos métodos não estáticos, você pode acessar diretamente por causa dessa referência (também nos construtores), mas para acessar nos métodos estáticos, é necessário criar o objeto da classe.

Prashant
fonte
16

Modificadores de acesso em Java.

Modificadores de acesso Java são usados ​​para fornecer controle de acesso em Java.

1. Padrão:

Acessível apenas às classes no mesmo pacote.

Por exemplo,

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

Esse acesso é mais restrito que público e protegido, mas menos restrito que privado.

2. Público

Pode ser acessado de qualquer lugar. (Acesso Global)

Por exemplo,

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

Saída: Olá

3. Privado

Acessível apenas dentro da mesma classe.

Se você tentar acessar membros privados em uma classe em outra, lançará um erro de compilação. Por exemplo,

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4. Protegido

Acessível apenas às classes no mesmo pacote e às subclasses

Por exemplo,

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

Saída: Olá

Digite a descrição da imagem aqui

Affy
fonte
14
  • público - acessível de qualquer lugar do aplicativo.

  • padrão - acessível a partir do pacote.

  • protegido - acessível a partir do pacote e subclasses em outro pacote. também

  • privado - acessível apenas a partir de sua classe.

Shailendra Singh
fonte
14

Visível para o pacote. O padrão. Não são necessários modificadores.

Visível apenas para a turma ( particular ).

Visível para o mundo ( público ).

Visível para o pacote e todas as subclasses ( protegidas ).

Variáveis ​​e métodos podem ser declarados sem nenhum modificador chamado. Exemplos padrão:

String name = "john";

public int age(){
    return age;
}

Modificador de acesso privado - privado:

Métodos, variáveis ​​e construtores declarados privados só podem ser acessados ​​dentro da própria classe declarada. O modificador de acesso privado é o nível de acesso mais restritivo. Classe e interfaces não podem ser privadas.

Variáveis ​​declaradas privadas podem ser acessadas fora da classe se métodos públicos getter estiverem presentes na classe.

O uso do modificador privado é a principal maneira de um objeto se encapsular e ocultar dados do mundo exterior.

Exemplos:

Public class Details{

    private String name;

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

    public String getName(){
        return this.name;
    }
}

Modificador de acesso público - public:

Uma classe, método, construtor, interface etc. público declarado pode ser acessado de qualquer outra classe. Portanto, campos, métodos, blocos declarados dentro de uma classe pública podem ser acessados ​​de qualquer classe pertencente ao universo Java.

No entanto, se a classe pública que estamos tentando acessar estiver em um pacote diferente, ela ainda precisará ser importada.

Por causa da herança de classe, todos os métodos e variáveis ​​públicos de uma classe são herdados por suas subclasses.

Exemplo:

public void cal(){

}

Modificador de acesso protegido - protegido:

Variáveis, métodos e construtores declarados protegidos em uma superclasse podem ser acessados ​​apenas pelas subclasses de outro pacote ou qualquer classe dentro do pacote da classe dos membros protegidos.

O modificador de acesso protegido não pode ser aplicado à classe e interfaces. Métodos, campos podem ser declarados protegidos, no entanto, métodos e campos em uma interface não podem ser declarados protegidos.

O acesso protegido oferece à subclasse a chance de usar o método ou variável auxiliar, enquanto impede que uma classe não relacionada tente usá-lo.

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}
amila isura
fonte
12

Esta página escreve bem sobre o modificador de acesso protegido e padrão

.... Protegido: o modificador de acesso protegido é um pouco complicado e você pode dizer que é um superconjunto do modificador de acesso padrão. Os membros protegidos são iguais aos membros padrão no que diz respeito ao acesso no mesmo pacote. A diferença é que, os membros protegidos também são acessíveis às subclasses da classe na qual o membro é declarado e que estão fora do pacote em que a classe pai está presente.

Mas esses membros protegidos são "acessíveis fora do pacote apenas por herança". ou seja, você pode acessar um membro protegido de uma classe em sua subclasse presente em algum outro pacote diretamente como se o membro estivesse presente na própria subclasse. Mas esse membro protegido não estará acessível na subclasse fora do pacote usando a referência da classe pai. ....

dameng
fonte
Apenas para adicionar isso "Quando o filho obtém acesso ao membro protegido da classe pai, ele se torna membro privado (ou melhor, eu diria que um membro privado especial que pode ser herdado pelas subclasses da subclasse)".
Anand
9

A resposta de David fornece o significado de cada modificador de acesso. Quanto a quando usar cada uma, sugiro tornar públicas todas as classes e os métodos de cada classe destinados ao uso externo (sua API) e todo o resto privado.

Com o tempo, você desenvolverá um senso de quando tornar algumas classes privadas de pacotes e quando declarar certos métodos protegidos para uso em subclasses.

Dov Wasserman
fonte
6

Nota: Este é apenas um complemento para a resposta aceita.

Isso está relacionado aos Java Access Modifiers .

Dos modificadores de acesso Java :

Um modificador de acesso Java especifica quais classes podem acessar uma determinada classe e seus campos, construtores e métodos. Modificadores de acesso podem ser especificados separadamente para uma classe, seus construtores, campos e métodos. Às vezes, os modificadores de acesso Java também são referidos na fala diária como especificadores de acesso Java, mas o nome correto é modificadores de acesso Java. Classes, campos, construtores e métodos podem ter um dos quatro modificadores de acesso Java diferentes:

  • Item da lista
  • privado
  • padrão (pacote)
  • protegido
  • público

De tutoriais sobre controle de acesso a membros de uma classe :

Modificadores de nível de acesso determinam se outras classes podem usar um campo específico ou invocar um método específico. Existem dois níveis de controle de acesso:

  • No nível superior - público ou privado do pacote (sem modificador explícito).
  • No nível do membro - público, privado, protegido ou pacote-privado (sem modificador explícito).

Uma classe pode ser declarada com o modificador public; nesse caso, essa classe é visível para todas as classes em todos os lugares. Se uma classe não tiver modificador (o padrão, também conhecido como pacote-privado), ela estará visível apenas dentro de seu próprio pacote

A tabela a seguir mostra o acesso aos membros permitidos por cada modificador.

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
 Modifier     Class  Package  Subclass  World 
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
 public       Y      Y        Y         Y     
 protected    Y      Y        Y         N     
 no modifier  Y      Y        N         N     
 private      Y      N        N         N     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

A primeira coluna de dados indica se a própria classe tem acesso ao membro definido pelo nível de acesso. Como você pode ver, uma classe sempre tem acesso a seus próprios membros. A segunda coluna indica se as classes no mesmo pacote da classe (independentemente de sua origem) têm acesso ao membro. A terceira coluna indica se as subclasses da classe declarada fora deste pacote têm acesso ao membro. A quarta coluna indica se todas as classes têm acesso ao membro.

Os níveis de acesso afetam você de duas maneiras. Primeiro, quando você usa classes que vêm de outra fonte, como as classes na plataforma Java, os níveis de acesso determinam quais membros dessas classes suas próprias classes podem usar. Segundo, quando você escreve uma classe, precisa decidir qual nível de acesso cada variável de membro e todo método em sua classe deve ter.

ישו אוהב אותך
fonte
1
o que exatamente é o suplemento e por que não é uma edição da postagem existente?
precisa
o complemento é modificadores de acesso. Por que não uma edição? Manter a resposta aceita inalterada por uma questão histórica e dar minha resposta.
ישו אוהב אותך
5

Padrão protegido público e privado são modificadores de acesso.

Eles são destinados ao encapsulamento, ou ocultar e mostrar o conteúdo da classe.

  1. A classe pode ser pública ou padrão
  2. Os alunos podem ser públicos, protegidos, padrão ou privados.

Privado não está acessível fora da classe O padrão está acessível apenas no pacote. Protegido no pacote, bem como em qualquer classe que o estenda. O público está aberto a todos.

Normalmente, as variáveis ​​de membro são definidas como privadas, mas os métodos de membro são públicos.

richa_v
fonte
Defaultnão é um modificador de acesso e dois dos outros estão incorretos.
Marquês de Lorne
5

Muitas vezes percebi que a lembrança dos conceitos básicos de qualquer linguagem pode ser possível através da criação de analogias do mundo real. Aqui está minha analogia para entender os modificadores de acesso em Java:

Vamos supor que você seja estudante de uma universidade e tenha um amigo que irá visitá-lo no fim de semana. Suponha que exista uma grande estátua do fundador da universidade no meio do campus.

  • Quando você o traz para o campus, a primeira coisa que você e seu amigo vêem é esta estátua. Isso significa que qualquer pessoa que entre no campus pode olhar para a estátua sem a permissão da universidade. Isso torna a estátua como pública .

  • Em seguida, você quer levar seu amigo para o seu dormitório, mas para isso precisa registrá-lo como visitante. Isso significa que ele recebe um passe de acesso (que é igual ao seu) para entrar em vários prédios do campus. Isso tornaria seu cartão de acesso como PROTEGIDO .

  • Seu amigo deseja fazer login no WiFi do campus, mas não possui credenciais para isso. A única maneira de ele ficar online é se você compartilhar seu login com ele. (Lembre-se, todo aluno que frequenta a universidade também possui essas credenciais de login). Isso tornaria suas credenciais de login como SEM MODIFICADOR .

  • Por fim, seu amigo deseja ler o relatório de andamento do semestre, publicado no site. No entanto, todo aluno tem seu próprio login pessoal para acessar esta seção do site do campus. Isso tornaria essas credenciais como PRIVADAS .

Espero que isto ajude!

Greedy Coder
fonte
4

Quando você estiver pensando em modificadores de acesso, pense nisso dessa maneira (se aplica a variáveis e métodos ):

public-> acessível de qualquer lugar
private-> acessível somente dentro da mesma classe em que é declarado

Agora, a confusão surge quando se trata defaulteprotected

default-> Nenhuma palavra-chave do modificador de acesso está presente. Isso significa que está disponível estritamente dentro do pacote da classe. Em nenhum lugar fora desse pacote ele pode ser acessado.

protected-> Um pouco menos rigoroso que defaulte, além das mesmas classes de pacotes, ele pode ser acessado por subclasses fora do pacote declarado.

Pritam Banerjee
fonte
4

O acesso Java modifica o que você pode usar

insira a descrição da imagem aqui

Modificador de acesso pode ser aplicável para class, field[Sobre] , method. Tente acessar, subclasse ou substituir isso.

  • O acesso fieldou methodé através de a class.
  • Herança. O classmodificador de acesso sucessor (subclasse) pode ser qualquer um. O methodmodificador de acesso sucessor (substituição) deve ser o mesmo ou expandi-lo

A classe de nível superior (escopo de primeiro nível) pode ser publice default. Nested class[Sobre] pode ter qualquer um deles

package não se aplica à hierarquia de pacotes

Modificadores de acesso rápido

yoAlex5
fonte
2

É tudo sobre encapsulamento (ou, como Joe Phillips afirmou, menos conhecimento ).

Comece com o mais restritivo (privado) e veja se você precisa de modificadores menos restritivos posteriormente.

Todos nós usamos modificadores de método e membro como privado, público, ... mas uma coisa que poucos desenvolvedores fazem é usar pacotes para organizar o código logicamente.

Por exemplo: Você pode colocar métodos de segurança confidenciais em um pacote de 'segurança'. Em seguida, coloque uma classe pública que acesse parte do código relacionado à segurança neste pacote, mas mantenha outras classes de segurança privadas . Portanto, outros desenvolvedores só poderão usar a classe disponível publicamente fora deste pacote (a menos que alterem o modificador). Este não é um recurso de segurança, mas orientará o uso.

Outside world -> Package (SecurityEntryClass ---> Package private classes)

Outra coisa é que as classes que dependem muito umas das outras podem terminar no mesmo pacote e, eventualmente, podem ser refatoradas ou mescladas se a dependência for muito forte.

Se, pelo contrário, você definir tudo como público , não ficará claro o que deve ou não ser acessado, o que pode levar à criação de muitos javadoc (que não impõem nada por meio do compilador ...).

Christophe Roussy
fonte
2

analogia perfeita privada protegida pelo público para os tipos de dados variáveis

O diagrama de blocos a seguir explica como os membros de dados da classe base são herdados quando o modo de acesso à classe derivada é privado .

insira a descrição da imagem aqui

Nota: Declarar membros de dados com especificador de acesso privado é conhecido como ocultação de dados.

Fonte: Especificadores de acesso - privados, públicos e protegidos

leonidaa
fonte
1
A questão era sobre Java, não C ++.
Benoit
1
@ Benoit Mas o que eu postei, as fotos em especial, não são as mesmas para ambos: java e c ++? Essas regras também não se aplicam a java? obrigado
leonidaa 22/09/19
2
Em C ++, existem apenas 3 modificadores, enquanto existem 4 em java.
Benoit
1
a analogia é boa, mas o especificador de acesso padrão está ausente,
ms
1
O OP fez a pergunta "Qual é a diferença entre público, protegido, pacote privado e privado em Java?"
JL_SO
2

Meus dois centavos :)

privado:

classe -> uma classe de nível superior não pode ser privada. classes internas podem ser privadas, acessíveis a partir da mesma classe.

variável de instância -> acessível apenas na classe. Não é possível acessar fora da classe.

pacote-privado:

classe -> uma classe de nível superior pode ser privada de pacotes. Só pode ser acessível a partir do mesmo pacote. Não do subpacote, não do pacote externo.

variável de instância -> acessível a partir do mesmo pacote. Não do subpacote, não do pacote externo.

protegido:

classe -> uma classe de nível superior não pode ser protegida.

variável de instância -> Acessível apenas no mesmo pacote ou subpacote. Só pode ter acesso fora do pacote enquanto estende a classe.

público:

classe -> acessível no pacote / subpacote / outro pacote

variável de instância -> acessível em package / subpackage / outro pacote

Aqui está a resposta detalhada

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md

Mudassar
fonte
1
  • público

    Se um membro da classe for declarado com public, poderá ser acessado de qualquer lugar

  • protegido

    Se um membro da classe for declarado com a palavra-chave protegida, poderá ser acessado pelos mesmos membros da classe, fora dos membros da mesma classe no mesmo pacote e dos membros herdados da classe. Se um membro da classe estiver protegido, ele NÃO poderá ser acessado a partir da classe externa do pacote, a menos que a classe externa do pacote seja herdada, ou seja, estenda a outra superclasse do pacote. Mas um membro da classe protegido está sempre disponível para as mesmas classes de pacotes, NÃO importa o tempo, a mesma classe de pacote é herdada ou NÃO

  • padrão

    Em Java, o padrão NÃO é uma palavra-chave do modificador de acesso. Se um membro da classe for declarado sem nenhuma palavra-chave do modificador de acesso, nesse caso, será considerado como membro padrão. O membro da classe padrão está sempre disponível para os mesmos membros da classe do pacote. Mas o membro da classe de pacote externo NÃO pode acessar os membros da classe padrão, mesmo que as classes externas sejam subclasses ao contrário dos membros protegidos

  • privado

    Se um membro da classe for declarado com a palavra-chave protegida, nesse caso, ele estará disponível APENAS para os mesmos membros da classe

alexvipul
fonte
-1

Especificadores de acesso em Java: existem 4 especificadores de acesso em java, a saber, privado, pacote privado (padrão), protegido e público em ordem crescente de acesso.

Privado : quando você está desenvolvendo alguma classe e deseja que um membro dessa classe não seja exposto fora dessa classe, declare-o como privado. membros privados podem ser acessados ​​somente na classe em que estão definidos, ou seja, classe anexa. membros privados podem ser acessados ​​na referência 'this' e também em outras instâncias da classe que envolvem esses membros, mas apenas dentro da definição dessa classe.

Pacote privado (padrão) : este especificador de acesso fornecerá o acesso especificado pelo especificador de acesso privado, além do acesso descrito abaixo.

Quando você está desenvolvendo algum pacote e, portanto, alguma classe (digamos, Class1) dentro dele, você pode usar o especificador de acesso padrão (não precisa ser mencionado explicitamente), para expor o membro dentro da classe, para outras classes dentro do seu (mesmo) pacote. Nessas outras classes (dentro do mesmo pacote), você pode acessar esses membros padrão na instância da Class1. Além disso, você pode acessar esses membros padrão nas subclasses da Classe1, por exemplo, Classe2 (nesta referência ou na instância da Classe1 ou na instância da Classe2).

Basicamente, dentro do mesmo pacote, você pode acessar membros padrão na instância da classe diretamente ou na referência 'this' nas subclasses.

protected : Este especificador de acesso fornecerá o acesso especificado pelo especificador de acesso privado ao pacote, além do acesso descrito abaixo.

Quando você estiver desenvolvendo algum pacote e, portanto, alguma classe (digamos Class1) dentro dele, deverá usar o especificador de acesso protegido para membro de dados na Class1 se não desejar que esse membro seja acessado fora do pacote (digamos no pacote de consumidor de seu pacote, ou seja, cliente que está usando suas APIs) em geral, mas você deseja fazer uma exceção e permitir acesso a esse membro apenas se o cliente gravar a classe dizer Class2 que estende a Class1. Portanto, em geral, os membros protegidos estarão acessíveis nessa referência 'em' classes derivadas, ou seja, Classe2 e também em instâncias explícitas da Classe2.

Observe:

  1. Você não poderá acessar o membro protegido herdado da Class1 na Class2, se tentar acessá-lo na instância explícita da Class1, embora ele seja herdado.
  2. Quando você escreve outra classe Class3 dentro do mesmo / pacote diferente que estende a Class2, o membro protegido da Class1 estará acessível nessa referência e também na instância explícita da Class3. Isso será verdadeiro para qualquer hierarquia estendida, ou seja, o membro protegido ainda estará acessível nessa referência ou instância da classe estendida. Observe que na Class3, se você criar uma instância da Class2, não poderá acessar o membro protegido da Class1, embora ele seja herdado.

Portanto, os membros protegidos podem ser acessados ​​em outros pacotes, apenas se alguma classe desse outro pacote estender a classe que encerra esse membro protegido e o membro protegido for acessado na referência 'this' ou instâncias explícitas da classe estendida, dentro da definição de extensão classe.

público : esse especificador de acesso fornecerá o acesso especificado pelo especificador de acesso protegido, além do acesso descrito abaixo.

Quando você estiver desenvolvendo algum pacote e, portanto, alguma classe (por exemplo, Class1) dentro dele, use o especificador de acesso público para o membro de dados da Class1 se desejar que esse membro seja acessível em outros pacotes na instância da Class1 criada em alguma classe de outra classe. pacote. Basicamente, esse especificador de acesso deve ser usado quando você pretende expor seu membro de dados ao mundo sem nenhuma condição.

Tushar Baviskar
fonte