Pergunta

Considere o seguinte caso:

public class A {
  public A() { b = new B(); }
  B b;
  private class B { }
}

A partir de um aviso no Eclipse I citação que: o java compilador emula o A.B. construtor () por um método de acesso sintético. Suponho que o compilador agora vai em frente e cria um extra "debaixo de água" construtor para B.

Eu sinto que este é um pouco estranho: por que a classe B não sejam visíveis como a.k.o. campo em um? E: isso significa que a classe B não é mais privada em tempo de execução? E: por que se comporta a palavra-chave protegido para a classe B diferente

public class A {
  public A() { b = new B(); }
  B b;
  protected class B { }
}
Foi útil?

Solução

Classes internas são essencialmente um hack introduzido em Java 1.1. O JVM na verdade não tem qualquer conceito de uma classe interna, e assim o compilador tem que bodge-lo. O compilador gera classe B "fora" da classe A, mas no mesmo pacote, e em seguida, adiciona acessores sintéticos / construtores a ele para permitir que um para obter acesso a ele.

Quando você dá a B um construtor protegido, um pode acessar o construtor já que é no mesmo pacote, sem a necessidade de um construtor sintético a ser adicionado.

Outras dicas

Eu sei que esta questão é agora quase três anos, mas acho que uma parte da pergunta ainda não foi respondida:

E:? Isso significa que a classe B não é mais privada em tempo de execução

Carlos Heubergers comentário sobre skaffmans resposta sugere, classe B ainda é private para outras classes no pacote.

Ele provavelmente está certo para a linguagem de programação Java, ou seja, não é possível para se referir a B classe a partir de uma outra classe. Pelo menos não sem usar reflexão (com o qual também membros de classe privada pode ser acessado a partir do exterior), mas isso é outra questão.

Mas, como a JVM não tem qualquer conceito de uma classe interna (como estados skaffman), eu me perguntava como uma "acessível por apenas uma classe" A visibilidade é realizado no nível de bytecode. A resposta: Não é realizado em todos, para o JVM os olhares classe interna como uma classe privada pacote normal. Isto é, se você escrever bytecode para si mesmo (ou modificar um gerado pelo compilador) você pode acessar classe B sem problemas.

Você pode acessar todos os métodos sintéticos acessores de todas as classes no mesmo pacote, também. Então, se você atribuir um valor a um campo particular de A classe em um método de B classe, um método de acesso sintético com padrão (ou seja, pacote confidencial) a visibilidade é gerado em A classe (nomeado algo como access$000) que define o valor para você. Este método é suposto ser chamado apenas de B classe (e na verdade ele só pode ser chamado de lá usando a linguagem Java). Mas, do ponto de vista JVMs, este é apenas um método como qualquer outro e pode ser chamado por qualquer classe.

Assim, para responder à pergunta:

  • A partir das linguagens Java ponto de vista, classe B é e estadias privadas.
  • Do ponto de vista, B classe (ou melhor: A$B classe) JVMs. Não é privado

O acesso de class B e seu construtor não tem que ser o mesmo. Você pode ter uma classe interna privada com um construtor pacote de escopo, e isso é o que eu costumo fazer.

public class A {
  public A() { b = new B(); }
  B b;
  private class B {
    B() { }
  }
}

Você precisa usar

this.new B();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top