Vamos apenas dizer por que a classe externa não pode ser protegida? As classes internas podem ser protegidas.
945
Respostas:
102
Porque não faz sentido.
O membro da classe protegida (método ou variável) é semelhante ao pacote privado (visibilidade padrão), exceto que também pode ser acessado a partir de subclasses.
Já que não existe um conceito como 'subpacote' ou 'herança de pacote' em Java, declarar classe protegida ou pacote privado seria a mesma coisa.
No entanto, você pode declarar as classes aninhadas e internas como protegidas ou privadas.
> Visto que não existe um conceito como 'subpacote' ou 'herança de pacote' em Java, declarar classe protegida ou pacote privado seria a mesma coisa. Por que a classe protegida teria a mesma visibilidade que o pacote privado? Não é o mesmo que público? Obrigado.
yaromir 01 de
@Nikita Ryback Você pode explicar o que é subPacote ou herança de pacote? Ainda não estou claro por que protected é usado na classe de nível superior.
App Kart de
Quando você declara o membro da classe como protegido, sua visibilidade é das classes no mesmo pacote (chamadas de acesso ao pacote) e da Subclasse . Se você tentar acessar de uma classe externa em outro pacote, este membro do método protegido não ficará visível.
kelgwiin
@kelgwiin Eu acredito que você não deve misturar modificadores de acesso de classes e de membros. Porque os dois são diferentes. Embora as classes possam ser modificadas como públicas ou padrão, os membros podem ser modificados como públicas, privadas, protegidas e padrão.
sharhp de
2
"Porque não faz sentido" - é uma afirmação bastante ousada. Não está definido em Java, mas as coisas semelhantes que existem; por exemplo, openem Kotlin que permite subclasses fora do pacote atual (pode-se imaginar protectedem Java evitando isso, com o padrão oposto).
Raphael
41
Como você sabe, o padrão é para acesso de nível de pacote e protegido é para nível de pacote mais classes não-pacote, mas que estende esta classe (o ponto a ser observado aqui é que você pode estender a classe apenas se estiver visível!). Vamos colocar desta forma:
classe protegida de nível superior seria visível para classes em seu pacote.
agora torná-lo visível fora do pacote (subclasses) é um pouco confuso e complicado. Quais classes devem ter permissão para herdar nossa classe protegida?
Se todas as classes tiverem permissão para subclasses, será semelhante ao especificador de acesso público.
Se nenhum, é semelhante ao padrão.
Visto que não há como restringir esta classe sendo subclassificada por apenas algumas classes (não podemos restringir a classe sendo herdada por apenas algumas classes de todas as classes disponíveis em um pacote / fora de um pacote), não há uso de especificadores de acesso protegido para classes de nível superior. Portanto, não é permitido.
"agora, tornar uma classe protegida visível fora do pacote (subclasses) é um pouco confuso e complicado. Quais classes devem ter permissão para herdar nossa classe protegida? e se todas as classes tiverem permissão para subclasses, será semelhante ao especificador de acesso público." realmente me ajudou a entender o problema de por que classes protegidas não fazem sentido :)
A resposta de @Nikita Rybak tem bons pontos, mas falta de detalhes, eu não posso simplesmente pegar a ideia sem pensar profundamente, o seguinte é o que pensei e agora devo entender completamente o motivo.
Quatro modificadores de acesso, suponha que o 1º nível seja público e o 4º nível seja privado (com base nesta tabela em sequência). A primeira coisa que devemos saber é por que a classe não pode ser definida como privada no nível superior.
Portanto, se "private class foo" (um membro privado definido, isto é, a própria classe é um membro) permitir, qual é a externa (que contém o membro)? Escopo do arquivo? Não, o arquivo externo é inútil porque até mesmo várias classes em um único arquivo serão compiladas em arquivos de classe separados. Portanto, o exterior é um pacote . Mas o modificador de acesso padrão de terceiro nível já significa "pacote privado ". Portanto, o modificador de acesso privado de 4º nível não será usado / permitido.
Mas a classe privada aninhada é permitida porque o externo direto é a classe, não o pacote, por exemplo :
classPrivateNestedMain{
privatestaticclassInner{
publicstaticvoidmain(String[] args){
System.out.println("Hello from Inner!");
}
}
}
E se a "classe protegida foo" permitir? A principal característica protegida é a subclasse, então o (pacote) externo DEVE (devido ao escopo atualizado, mas ainda é opcional) fornecer estilo de subclasse , ou seja, sub-pacote, ou package A extends package B, mas não sabemos tal coisa. Portanto, protected não pode usar todo o potencial (o escopo principal abrange toda a subclasse) no nível superior em que o externo é o pacote (ou seja, não existe tal sub-pacote), mas protected pode usar todo o potencial na classe aninhada em que o externo é a classe ou seja, pode ser uma subclasse) :
classProtectedNestedMain{
protectedstaticclassInner{
publicstaticvoidmain(String[] args){
System.out.println("Hello from Inner!");
}
}
}
Observe que o dito acima "não pode usar todo o potencial" devido ao fato de não poder atingir toda a subclasse simplesmente porque nenhuma subclasse externa, isso significa que realmente protegido pode ser permitido , é apenas uma questão de escolha para evitar duplicar o trabalho do pacote -private se externo não for capaz de subclasse , veja abaixo.
Se o 1º nível (público) e o 3º nível (pacote privado) são permitidos, como o 2º nível intermediário (protegido) não é permitido?
subclasse de suporte público tão fácil de enganar. A maneira correta de ler esta tabela é
subclasse de suporte público se o externo tiver recurso de subclasse
O mesmo engano se aplica a package-private, package-private não suporta subclasse ( N na célula) não significa que o conceito de subclasse se aplica a outer.
Isso significa que devemos ignorar a coluna Subclasse se o recurso de subclasse não estiver disponível em externo:
Como podemos ver agora, tanto protected quanto package-private estão no mesmo nível agora ( YYN ), sem mais confusão sobre por que o nível intermediário não é permitido. No geral, o Java escolhe apenas pacote privado em vez de protegido para evitar confusão ( é apenas uma questão de escolha , mas a característica principal protegida é a subclasse, então pacote privado é superior), e o resultado , apenas 2 modificadores de acesso permitidos no nível superior:
No nível superior - público ou privado de pacote (sem modificador explícito).
Definir um campo protegido torna esse campo acessível dentro do pacote, bem como fora do pacote apenas por herança (somente dentro da classe filha).
Portanto, se tivermos permissão para tornar uma classe protegida, podemos acessá-la dentro do pacote muito facilmente, mas para acessar essa classe fora do pacote, primeiro precisamos estender aquela entidade na qual essa classe está definida, que é o seu pacote.
E uma vez que um pacote não pode ser estendido (pode ser importado), definir uma classe protegida tornará novamente o pacote privado, o que é semelhante a defini-lo como padrão, o que já podemos fazer. Portanto, não há benefício em definir uma classe privada; isso apenas tornará as coisas ambíguas.
Protegido não é semelhante ao público. Protected tem ambos os níveis de acesso de pacote e pode ser acessado fora dos pacotes apenas por herança. Se uma classe diz A fora de um pacote HERDE uma classe de outro pacote (com o método protegido usando HERANÇA), ela pode acessar os métodos desta classe B que tem métodos protegidos, mas as subclasses derivadas desta classe, ou seja, A não pode acessar os métodos protegidos ... o oposto acontece com public ..
comportamento de “protegido” = comportamento de “padrão” + “usar em qualquer subclasse de qualquer pacote”.
De qualquer forma, temos um modificador de acesso padrão para a classe, a única vantagem que podemos obter do modificador de acesso protegido é: - usando-o em qualquer pacote por meio de subclasses. Mas para a subclasse, a visibilidade da classe pai “protegida” seria privada. Portanto, não pode ser acessado. Basicamente, se você tiver uma classe de nível superior protegida, nenhuma classe externa poderá obter acesso criando uma subclasse dela. Tão protegido para uma classe de nível superior não tem sentido.
A resposta de @ Akash5288 não fazia sentido para mim:
Se todas as classes tiverem permissão para subclasses, será semelhante ao especificador de acesso público.
Visto que não há como restringir esta classe sendo subclassificada por apenas algumas classes (não podemos restringir a classe sendo herdada por apenas algumas classes de todas as classes disponíveis em um pacote / fora de um pacote), não há uso de especificadores de acesso protegido para classes de nível superior. Portanto, não é permitido.
Você pode então aplicar a mesma lógica a métodos e variáveis protegidos, eles também são "semelhantes ao público". Todas as classes fora de um pacote podem estender nossa classe pública e usar seus métodos protegidos. Por que restringir métodos e variáveis a classes estendidas está ok, mas restringir a classe inteira não? "Semelhante ao público" não é "o mesmo que público". Minha interpretação é que está perfeitamente bem permitir uma classe protegida, assim como está bem permitir métodos protegidos.
A resposta "você não pode estender uma aula que não pode acessar / ver" é mais lógica.
O que faz sentido para esta pergunta é que, JVM é escrito em C (Sun JVM) e C ++ (oracle JVM) então durante a compilação, vamos criar arquivos .class fora de nosso arquivo java e se declararmos uma classe com a palavra-chave Protected então não será acessado pela JVM.
A resposta por que a classe protegida não será acessada pela JVM é que, uma vez que os campos protegidos são acessíveis dentro do mesmo pacote ou para um pacote diferente apenas por herança e a JVM não é escrita de forma que herde a classe. Espero que isso responda a esta questão :)
Da mesma forma, uma classe de nível superior não pode ser privada. Explicação como abaixo:
Então o que acontecerá se definirmos uma classe privada, essa classe só será acessível dentro da entidade na qual ela está definida, que no nosso caso é seu pacote?
Portanto, definir o acesso privado à classe o tornará acessível dentro do mesmo pacote que a palavra-chave padrão já faz para nós. Portanto, não há benefício em definir uma classe privada, isso apenas tornará as coisas ambíguas.
protegido significa que o membro pode ser acessado por qualquer classe no mesmo pacote e por subclasses, mesmo se estiverem em outros pacotes.
Exemplo:
package a;
classparent{
protectedvoidp();
}
package b;
import a.p;
classchildextendsparent{
//you can access method which is protected in the parent in the child
}
classanotherextendschild{
//here you can not access the protected method
}
se uma classe externa for declarada por protected, acho que você deseja que a classe só possa ser acessada do mesmo pacote e sua subclasse, mas de pacotes diferentes. Porém, não é possível criar subclasses para uma classe protegida, pois quando você escreve "classe Cachorro estende Animal", por causa de protegida "Animal" só pode ser acessada por sua subclasse, obviamente, "Cachorro" não é subclasse "Animal" .
Portanto, a classe externa protegida é igual à classe externa (padrão)!
Respostas:
Porque não faz sentido.
O membro da classe protegida (método ou variável) é semelhante ao pacote privado (visibilidade padrão), exceto que também pode ser acessado a partir de subclasses.
Já que não existe um conceito como 'subpacote' ou 'herança de pacote' em Java, declarar classe protegida ou pacote privado seria a mesma coisa.
No entanto, você pode declarar as classes aninhadas e internas como protegidas ou privadas.
fonte
open
em Kotlin que permite subclasses fora do pacote atual (pode-se imaginarprotected
em Java evitando isso, com o padrão oposto).Como você sabe, o padrão é para acesso de nível de pacote e protegido é para nível de pacote mais classes não-pacote, mas que estende esta classe (o ponto a ser observado aqui é que você pode estender a classe apenas se estiver visível!). Vamos colocar desta forma:
Visto que não há como restringir esta classe sendo subclassificada por apenas algumas classes (não podemos restringir a classe sendo herdada por apenas algumas classes de todas as classes disponíveis em um pacote / fora de um pacote), não há uso de especificadores de acesso protegido para classes de nível superior. Portanto, não é permitido.
fonte
public class A { protected class B { } }
fonte
A resposta de @Nikita Rybak tem bons pontos, mas falta de detalhes, eu não posso simplesmente pegar a ideia sem pensar profundamente, o seguinte é o que pensei e agora devo entender completamente o motivo.
Quatro modificadores de acesso, suponha que o 1º nível seja público e o 4º nível seja privado (com base nesta tabela em sequência). A primeira coisa que devemos saber é por que a classe não pode ser definida como privada no nível superior.
Portanto, se "private class foo" (um membro privado definido, isto é, a própria classe é um membro) permitir, qual é a externa (que contém o membro)? Escopo do arquivo? Não, o arquivo externo é inútil porque até mesmo várias classes em um único arquivo serão compiladas em arquivos de classe separados. Portanto, o exterior é um pacote . Mas o modificador de acesso padrão de terceiro nível já significa "pacote privado ". Portanto, o modificador de acesso privado de 4º nível não será usado / permitido.
Mas a classe privada aninhada é permitida porque o externo direto é a classe, não o pacote, por exemplo :
class PrivateNestedMain { private static class Inner { public static void main(String[] args) { System.out.println("Hello from Inner!"); } } }
E se a "classe protegida foo" permitir? A principal característica protegida é a subclasse, então o (pacote) externo DEVE (devido ao escopo atualizado, mas ainda é opcional) fornecer estilo de subclasse , ou seja, sub-pacote, ou
package A extends package B
, mas não sabemos tal coisa. Portanto, protected não pode usar todo o potencial (o escopo principal abrange toda a subclasse) no nível superior em que o externo é o pacote (ou seja, não existe tal sub-pacote), mas protected pode usar todo o potencial na classe aninhada em que o externo é a classe ou seja, pode ser uma subclasse) :class ProtectedNestedMain { protected static class Inner { public static void main(String[] args) { System.out.println("Hello from Inner!"); } } }
Observe que o dito acima "não pode usar todo o potencial" devido ao fato de não poder atingir toda a subclasse simplesmente porque nenhuma subclasse externa, isso significa que realmente protegido pode ser permitido , é apenas uma questão de escolha para evitar duplicar o trabalho do pacote -private se externo não for capaz de subclasse , veja abaixo.
Minha confusão é causada principalmente pela famosa tabela em https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :
Se o 1º nível (público) e o 3º nível (pacote privado) são permitidos, como o 2º nível intermediário (protegido) não é permitido?
subclasse de suporte público tão fácil de enganar. A maneira correta de ler esta tabela é
O mesmo engano se aplica a package-private, package-private não suporta subclasse ( N na célula) não significa que o conceito de subclasse se aplica a outer.
Isso significa que devemos ignorar a coluna Subclasse se o recurso de subclasse não estiver disponível em externo:
Como podemos ver agora, tanto protected quanto package-private estão no mesmo nível agora ( YYN ), sem mais confusão sobre por que o nível intermediário não é permitido. No geral, o Java escolhe apenas pacote privado em vez de protegido para evitar confusão ( é apenas uma questão de escolha , mas a característica principal protegida é a subclasse, então pacote privado é superior), e o resultado , apenas 2 modificadores de acesso permitidos no nível superior:
fonte
Definir um campo protegido torna esse campo acessível dentro do pacote, bem como fora do pacote apenas por herança (somente dentro da classe filha).
Portanto, se tivermos permissão para tornar uma classe protegida, podemos acessá-la dentro do pacote muito facilmente, mas para acessar essa classe fora do pacote, primeiro precisamos estender aquela entidade na qual essa classe está definida, que é o seu pacote.
E uma vez que um pacote não pode ser estendido (pode ser importado), definir uma classe protegida tornará novamente o pacote privado, o que é semelhante a defini-lo como padrão, o que já podemos fazer. Portanto, não há benefício em definir uma classe privada; isso apenas tornará as coisas ambíguas.
Para obter mais informações, leia Por que uma classe Java externa não pode ser privada ou protegida
fonte
Protegido não é semelhante ao público. Protected tem ambos os níveis de acesso de pacote e pode ser acessado fora dos pacotes apenas por herança. Se uma classe diz A fora de um pacote HERDE uma classe de outro pacote (com o método protegido usando HERANÇA), ela pode acessar os métodos desta classe B que tem métodos protegidos, mas as subclasses derivadas desta classe, ou seja, A não pode acessar os métodos protegidos ... o oposto acontece com public ..
Exemplo:
package 2; class B { protected void method1() { } } package 1; import 2.B; class A extends B { //can access protected method } class C extends A { //can't access the protected method }
fonte
comportamento de “protegido” = comportamento de “padrão” + “usar em qualquer subclasse de qualquer pacote”.
De qualquer forma, temos um modificador de acesso padrão para a classe, a única vantagem que podemos obter do modificador de acesso protegido é: - usando-o em qualquer pacote por meio de subclasses. Mas para a subclasse, a visibilidade da classe pai “protegida” seria privada. Portanto, não pode ser acessado. Basicamente, se você tiver uma classe de nível superior protegida, nenhuma classe externa poderá obter acesso criando uma subclasse dela. Tão protegido para uma classe de nível superior não tem sentido.
fonte
Protegido : VISÍVEL apenas no nível de pacote *.
a classe é definida como protegida ---> não pode ser estendida de fora do pacote (não visível).
E se não puder ser estendido, não faz sentido mantê-lo protegido , porque então ele se tornará padrão acesso permitido.
O mesmo se aplica a aulas particulares definidas.
Nota: As classes aninhadas ou internas podem ser definidas como protegidas ou privadas .
* : Explore a palavra-chave protegida , para esta resposta eu a tornei sucinta.
fonte
A resposta de @ Akash5288 não fazia sentido para mim:
Você pode então aplicar a mesma lógica a métodos e variáveis protegidos, eles também são "semelhantes ao público". Todas as classes fora de um pacote podem estender nossa classe pública e usar seus métodos protegidos. Por que restringir métodos e variáveis a classes estendidas está ok, mas restringir a classe inteira não? "Semelhante ao público" não é "o mesmo que público". Minha interpretação é que está perfeitamente bem permitir uma classe protegida, assim como está bem permitir métodos protegidos.
A resposta "você não pode estender uma aula que não pode acessar / ver" é mais lógica.
fonte
O que faz sentido para esta pergunta é que, JVM é escrito em C (Sun JVM) e C ++ (oracle JVM) então durante a compilação, vamos criar arquivos .class fora de nosso arquivo java e se declararmos uma classe com a palavra-chave Protected então não será acessado pela JVM.
A resposta por que a classe protegida não será acessada pela JVM é que, uma vez que os campos protegidos são acessíveis dentro do mesmo pacote ou para um pacote diferente apenas por herança e a JVM não é escrita de forma que herde a classe. Espero que isso responda a esta questão :)
Da mesma forma, uma classe de nível superior não pode ser privada. Explicação como abaixo:
Então o que acontecerá se definirmos uma classe privada, essa classe só será acessível dentro da entidade na qual ela está definida, que no nosso caso é seu pacote?
Portanto, definir o acesso privado à classe o tornará acessível dentro do mesmo pacote que a palavra-chave padrão já faz para nós. Portanto, não há benefício em definir uma classe privada, isso apenas tornará as coisas ambíguas.
fonte
protegido significa que o membro pode ser acessado por qualquer classe no mesmo pacote e por subclasses, mesmo se estiverem em outros pacotes.
Exemplo:
package a; class parent{ protected void p(); } package b; import a.p; class child extends parent{ //you can access method which is protected in the parent in the child } class another extends child { //here you can not access the protected method }
fonte
se uma classe externa for declarada por protected, acho que você deseja que a classe só possa ser acessada do mesmo pacote e sua subclasse, mas de pacotes diferentes. Porém, não é possível criar subclasses para uma classe protegida, pois quando você escreve "classe Cachorro estende Animal", por causa de protegida "Animal" só pode ser acessada por sua subclasse, obviamente, "Cachorro" não é subclasse "Animal" .
Portanto, a classe externa protegida é igual à classe externa (padrão)!
fonte