Classe Sub
é uma subclasse de classe Sup
. O que isso significa praticamente? Ou, em outras palavras, qual é o significado prático de "herança"?
Opção 1: o código de Sup é virtualmente copiado para Sub. (como em 'copiar e colar', mas sem o código copiado visualmente visto na subclasse).
Exemplo: methodA()
é um método originalmente em Sup. Sub estende Sup, assim methodA()
como (virtualmente) é copiado e colado para Sub. Agora Sub tem um método chamado methodA()
. É idêntico ao Sup methodA()
em todas as linhas de código, mas pertence inteiramente ao Sub - e não depende do Sup ou está relacionado ao Sup de qualquer forma.
Opção 2: o código de Sup não é realmente copiado para Sub. Ainda está apenas na superclasse. Mas esse código pode ser acessado através da subclasse e pode ser usado pela subclasse.
Exemplo: methodA()
é um método em Sup. Sub estende Sup, então agora methodA()
pode ser acessado através Sub assim: subInstance.methodA()
. Mas isso realmente invocará methodA()
na superclasse. O que significa que methodA () operará no contexto da superclasse, mesmo que tenha sido chamado pela subclasse.
Pergunta: Qual das duas opções é realmente como as coisas funcionam? Se nenhum deles for, descreva como essas coisas realmente funcionam.
fonte
Respostas:
Opção 2.
O bytecode é referenciado dinamicamente no tempo de execução: é por isso que, por exemplo, ocorrem LinkageErrors .
Por exemplo, suponha que você compile duas classes:
Agora modifique e recompile a classe pai sem modificar ou recompilar a classe filho :
Por fim, execute um programa que use a classe filho. Você receberá um NoSuchMethodError :
fonte
Vamos começar com duas classes simples:
e depois
Compilando methodA e observando o código de bytes que se obtém:
E você pode ver ali, com o método invokespecial, que faz a pesquisa no método A da classe Sup ().
O opcode invokepecial tem a seguinte lógica:
Nesse caso, não há método de instância com o mesmo nome e descritor em sua classe, portanto o primeiro marcador não será acionado. A segunda bala, no entanto - haverá uma superclasse e ela invocará o método A da super.
O compilador não alinha isso e não há cópia da fonte de Sup na classe.
No entanto, a história ainda não está concluída. Este é apenas ocódigo compilado . Quando o código atinge a JVM, o HotSpot pode se envolver.
Infelizmente, eu não sei muito sobre isso, então apelo à autoridade sobre este assunto e vou para Inlining em Java, onde é dito que o HotSpot pode incorporar métodos (mesmo métodos não finais).
Indo para os documentos , observe que, se uma chamada de método específica se tornar um hot spot, em vez de fazer essa pesquisa a cada vez, essas informações poderão ser incorporadas - copiando efetivamente o código do método Sup (A) para Sub methodA ().
Isso é feito em tempo de execução, na memória, com base em como o aplicativo está se comportando e quais otimizações são necessárias para acelerar o desempenho.
Conforme declarado no HotSpot Internals for OpenJDK, "Métodos são frequentemente incorporados. Invocações estáticas, privadas, finais e / ou" especiais "são fáceis de incorporar".
Se você pesquisar nas opções da JVM , encontrará uma opção de
-XX:MaxInlineSize=35
(35 sendo o padrão), que é o número máximo de bytes que podem ser incorporados. Vou salientar que é por isso que o Java gosta de ter muitos métodos pequenos - porque eles podem ser facilmente incorporados. Esses pequenos métodos se tornam mais rápidos quando são chamados mais porque podem ser incorporados. E, embora se possa brincar com esse número e aumentá-lo, isso pode fazer com que outras otimizações sejam menos eficazes. (questão SO relacionada: estratégia de inline do HotSpot JIT, que aponta várias outras opções para espiar os aspectos internos do inline que o HotSpot está fazendo).Portanto, não - o código não está embutido no momento da compilação. E sim - o código pode muito bem ser incorporado em tempo de execução se as otimizações de desempenho o justificarem.
E tudo o que escrevi sobre o HotSpot embutido se aplica apenas ao HotSpot JVM distribuído pela Oracle. Se você olhar a lista de máquinas virtuais Java da wikipedia, existem muito mais do que apenas HotSpot e a maneira como essas JVMs lidam com inlining pode ser completamente diferente do que eu descrevi acima. Apache Harmony, Dalvik, ART - as coisas podem funcionar de maneira diferente lá.
fonte
o código não é copiado, é acessado por referência:
compiladores podem otimizar como isso é representado / executado na memória, mas essa é basicamente a estrutura
fonte