No momento, estou fazendo uma atribuição para uma de minhas classes e, nela, tenho que dar exemplos, usando a sintaxe Java, de vinculação estática e dinâmica .
Eu entendo o conceito básico, que a vinculação estática acontece em tempo de compilação e a vinculação dinâmica acontece em tempo de execução, mas não consigo descobrir como elas realmente funcionam especificamente.
Encontrei um exemplo de vinculação estática online que dá este exemplo:
public static void callEat(Animal animal) {
System.out.println("Animal is eating");
}
public static void callEat(Dog dog) {
System.out.println("Dog is eating");
}
public static void main(String args[])
{
Animal a = new Dog();
callEat(a);
}
E que isso imprimiria "animal está comendo" porque a chamada para callEat
usa vinculação estática , mas não tenho certeza de por que isso é considerado vinculação estática.
Até agora, nenhuma das fontes que vi conseguiu explicar isso de uma forma que eu possa acompanhar.
java
dynamic-binding
static-binding
user2309750
fonte
fonte
Respostas:
Da postagem do blog revisitada por Javar :
fonte
Conectar uma chamada de método ao corpo do método é conhecido como Binding. Como disse Maulik, "A vinculação estática usa informações de tipo (classe em Java) para vinculação, enquanto a vinculação dinâmica usa Object para resolver a vinculação." Portanto, este código:
Irá produzir o resultado: o cão está comendo ... porque está usando a referência do objeto para descobrir qual método usar. Se mudarmos o código acima para este:
Ele produzirá: animal está comendo ... porque é um método estático, então está usando Type (neste caso Animal) para resolver qual método estático chamar. Ao lado dos métodos estáticos, os métodos private e final usam a mesma abordagem.
fonte
a
é realmente umDog
tempo de compilação?O compilador sabe apenas que o tipo de "a" é
Animal
; isso acontece em tempo de compilação, por isso é chamado de vinculação estática (sobrecarga de método). Mas se for uma vinculação dinâmica, ele chamaria oDog
método de classe. Aqui está um exemplo de vinculação dinâmica.Resultado: Método de alimentação interna do cão
fonte
Bem, para entender como a vinculação estática e dinâmica realmente funciona? ou como eles são identificados pelo compilador e JVM?
Vamos pegar o exemplo abaixo onde
Mammal
está uma classe pai que tem um métodospeak()
e umaHuman
classe extendsMammal
, sobrescreve ospeak()
método e, em seguida, novamente o sobrecarrega comspeak(String language)
.Quando compilamos o código acima e tentamos olhar para o bytecode usando
javap -verbose OverridingInternalExample
, podemos ver que o compilador gera uma tabela constante onde atribui códigos inteiros para cada chamada de método e código de byte para o programa que extraí e incluí no próprio programa ( veja os comentários abaixo de cada chamada de método)Ao olhar para o código acima, podemos ver que o bytecode de
humanMammal.speak()
,human.speak()
ehuman.speak("Hindi")
são totalmente diferentes (invokevirtual #4
,invokevirtual #7
,invokevirtual #9
) porque o compilador é capaz de diferenciar entre eles com base na lista de argumentos e referência de classe. Como tudo isso é resolvido estaticamente em tempo de compilação, é por isso que a sobrecarga de método é conhecida como polimorfismo estático ou ligação estática .Mas bytecode para
anyMammal.speak()
ehumanMammal.speak()
é o mesmo (invokevirtual #4
) porque de acordo com o compilador ambos os métodos são chamados naMammal
referência.Portanto, agora surge a pergunta: se ambas as chamadas de método têm o mesmo bytecode, como a JVM sabe qual método chamar?
Bem, a resposta está escondida no próprio bytecode e é um
invokevirtual
conjunto de instruções. O JVM usa ainvokevirtual
instrução para invocar o equivalente Java dos métodos virtuais C ++. Em C ++, se quisermos sobrescrever um método em outra classe, precisamos declará-lo como virtual, mas em Java, todos os métodos são virtuais por padrão porque podemos sobrescrever todos os métodos na classe filha (exceto métodos privados, finais e estáticos).Em Java, cada variável de referência contém dois ponteiros ocultos
Portanto, todas as referências de objeto contêm indiretamente uma referência a uma tabela que contém todas as referências de método desse objeto. Java pegou emprestado esse conceito de C ++ e essa tabela é conhecida como tabela virtual (vtable).
Uma vtable é uma estrutura semelhante a um array que contém nomes de métodos virtuais e suas referências nos índices de array. A JVM cria apenas uma vtable por classe ao carregar a classe na memória.
Portanto, sempre que a JVM encontra um
invokevirtual
conjunto de instruções, ela verifica a vtable dessa classe para a referência do método e invoca o método específico que, em nosso caso, é o método de um objeto, não a referência.Como tudo isso é resolvido apenas no tempo de execução e no tempo de execução a JVM consegue saber qual método invocar, é por isso que a Substituição de Método é conhecida como Polimorfismo Dinâmico ou simplesmente Polimorfismo ou Ligação Dinâmica .
Você pode ler mais detalhes no meu artigo Como a JVM trata a sobrecarga e a substituição de métodos internamente .
fonte
Existem três diferenças principais entre vinculação estática e dinâmica ao projetar os compiladores e como as variáveis e procedimentos são transferidos para o tempo de execução ambiente de . Essas diferenças são as seguintes:
Vinculação estática : na vinculação estática, três problemas a seguir são discutidos:
Definição de um procedimento
Declaração de um nome (variável, etc.)
Âmbito da declaração
Vinculação dinâmica : três problemas encontrados na vinculação dinâmica são os seguintes:
Ativação de um procedimento
Vinculação de um nome
Tempo de vida de uma encadernação
fonte
Com o método estático nas classes pai e filho: Static Binding
Vinculação dinâmica:
fonte
Todas as respostas aqui estão corretas, mas quero acrescentar algo que está faltando. quando você está substituindo um método estático, parece que o estamos substituindo, mas na verdade não é uma substituição de método. Em vez disso, é chamado de ocultação de método. Os métodos estáticos não podem ser substituídos em Java.
Veja o exemplo abaixo:
Na vinculação dinâmica, o método é chamado dependendo do tipo de referência e não do tipo de objeto que a variável de referência está mantendo. Aqui, a vinculação estática acontece porque a ocultação do método não é um polimorfismo dinâmico. Se você remover a palavra-chave estática na frente de eat () e torná-la um método não estático, ela mostrará o polimorfismo dinâmico e não ocultação de método.
Encontrei o link abaixo para apoiar minha resposta: https://youtu.be/tNgZpn7AeP0
fonte
No caso do tipo de ligação estática do objeto determinado no tempo de compilação, enquanto no tipo de ligação dinâmica do objeto é determinado no tempo de execução.
fonte
Porque o compilador conhece a ligação em tempo de compilação. Se você invocar um método em uma interface, por exemplo, o compilador não pode saber e a ligação é resolvida em tempo de execução porque o objeto real que tem um método invocado pode ser um entre vários. Portanto, isso é tempo de execução ou vinculação dinâmica.
Sua invocação está vinculada à classe Animal no momento da compilação porque você especificou o tipo. Se você passasse essa variável para outro método em outro lugar, ninguém saberia (além de você porque você a escreveu) que classe real seria. A única pista é o tipo declarado de Animal.
fonte