Actualmente estoy haciendo una tarea para una de mis clases, y en ella tengo que dar ejemplos, usando la sintaxis de Java, de enlace estático y dinámico .
Entiendo el concepto básico, que el enlace estático ocurre en tiempo de compilación y el enlace dinámico ocurre en tiempo de ejecución, pero no puedo entender cómo funcionan realmente específicamente.
Encontré un ejemplo de enlace estático en línea que da este ejemplo:
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);
}
Y que esto imprimiría "animal está comiendo" porque la llamada a callEat
usa enlace estático , pero no estoy seguro de por qué esto se considera enlace estático.
Hasta ahora, ninguna de las fuentes que he visto ha logrado explicar esto de una manera que pueda seguir.
java
dynamic-binding
static-binding
usuario2309750
fuente
fuente
Respuestas:
De la publicación de blog visitada por Java :
fuente
La conexión de una llamada de método al cuerpo del método se conoce como Binding. Como dijo Maulik, "el enlace estático utiliza información de tipo (clase en Java) para el enlace, mientras que el enlace dinámico utiliza Object para resolver el enlace". Entonces este código:
Producirá el resultado: el perro está comiendo ... porque está usando la referencia del objeto para encontrar qué método usar. Si cambiamos el código anterior a esto:
Producirá: animal está comiendo ... porque es un método estático, por lo que está usando Type (en este caso Animal) para resolver qué método estático llamar. Además de los métodos estáticos, los métodos privados y finales utilizan el mismo enfoque.
fuente
a
realidad es unDog
tiempo de compilación?El compilador solo sabe que el tipo de "a" es
Animal
; esto sucede en tiempo de compilación, por lo que se denomina enlace estático (sobrecarga de métodos). Pero si es un enlace dinámico, llamaría alDog
método de clase. A continuación, se muestra un ejemplo de enlace dinámico.Resultado: método de comer interior de perro
fuente
Bueno, para entender cómo la unión estática y dinámica funciona realmente el ? o ¿cómo se identifican mediante el compilador y la JVM?
Tomemos el siguiente ejemplo donde
Mammal
hay una clase padre que tiene un métodospeak()
y laHuman
clase se extiendeMammal
, anula elspeak()
método y luego lo sobrecarga de nuevospeak(String language)
.Cuando compilamos el código anterior e intentamos mirar el
javap -verbose OverridingInternalExample
código de bytes usando , podemos ver que el compilador genera una tabla constante donde asigna códigos enteros a cada llamada de método y código de bytes para el programa que he extraído e incluido en el programa mismo ( vea los comentarios debajo de cada llamada al método)Al observar el código de seguridad, podemos ver que el código de bytes de
humanMammal.speak()
,human.speak()
yhuman.speak("Hindi")
son totalmente diferentes (invokevirtual #4
,invokevirtual #7
,invokevirtual #9
) ya que el compilador es capaz de diferenciar entre ellos sobre la base de la lista de argumentos y la referencia de clase. Debido a que todo esto se resuelve en tiempo de compilación de forma estática, es por eso que la sobrecarga de métodos se conoce como polimorfismo estático o enlace estático .Pero el código de bytes para
anyMammal.speak()
yhumanMammal.speak()
es el mismo (invokevirtual #4
) porque, según el compilador, ambos métodos se llaman porMammal
referencia.Entonces, ahora surge la pregunta si ambas llamadas a métodos tienen el mismo código de bytes, ¿cómo sabe JVM a qué método llamar?
Bueno, la respuesta está oculta en el propio código de bytes y es un
invokevirtual
conjunto de instrucciones. JVM utiliza elinvokevirtual
instrucción para invocar el equivalente de Java de los métodos virtuales de C ++. En C ++, si queremos anular un método en otra clase, debemos declararlo como virtual, pero en Java, todos los métodos son virtuales de forma predeterminada porque podemos anular todos los métodos de la clase secundaria (excepto los métodos privados, finales y estáticos).En Java, cada variable de referencia contiene dos punteros ocultos
Entonces, todas las referencias a objetos contienen indirectamente una referencia a una tabla que contiene todas las referencias a métodos de ese objeto. Java ha tomado prestado este concepto de C ++ y esta tabla se conoce como tabla virtual (vtable).
Una vtable es una estructura similar a una matriz que contiene nombres de métodos virtuales y sus referencias en índices de matriz. JVM crea solo una tabla virtual por clase cuando carga la clase en la memoria.
Entonces, cada vez que JVM se encuentra con un
invokevirtual
conjunto de instrucciones, verifica la tabla vtable de esa clase para la referencia del método e invoca el método específico que en nuestro caso es el método de un objeto, no la referencia.Debido a que todo esto se resuelve solo en tiempo de ejecución y en tiempo de ejecución JVM llega a saber qué método invocar, es por eso que la Anulación de método se conoce como polimorfismo dinámico o simplemente polimorfismo o enlace dinámico .
Puede leer más detalles en mi artículo ¿Cómo maneja la JVM la sobrecarga y anulación de métodos internamente ?
fuente
Hay tres diferencias principales entre el enlace estático y dinámico al diseñar los compiladores y cómo se transfieren las variables y los procedimientos al entorno de ejecución . Estas diferencias son las siguientes:
Enlace estático : En el enlace estático se discuten los siguientes tres problemas:
Definición de un procedimiento
Declaración de un nombre (variable, etc.)
Alcance de la declaración
Enlace dinámico : los tres problemas que surgen en el enlace dinámico son los siguientes:
Activación de un procedimiento
Encuadernación de un nombre
Vida útil de una encuadernación
fuente
Con el método estático en la clase principal y secundaria: Enlace estático
Encuadernación dinámica:
fuente
Todas las respuestas aquí son correctas, pero quiero agregar algo que falta. cuando está anulando un método estático, parece que lo estamos anulando, pero en realidad no es un método anulado. En su lugar, se llama método de ocultación. Los métodos estáticos no se pueden anular en Java.
Mira el siguiente ejemplo:
En la vinculación dinámica, se llama al método dependiendo del tipo de referencia y no del tipo de objeto que contiene la variable de referencia. Aquí la vinculación estática sucede porque la ocultación del método no es un polimorfismo dinámico. Si elimina la palabra clave estática delante de eat () y la convierte en un método no estático, le mostrará el polimorfismo dinámico y no la ocultación de métodos.
Encontré el siguiente enlace para respaldar mi respuesta: https://youtu.be/tNgZpn7AeP0
fuente
En el caso del tipo de enlace estático del objeto determinado en el tiempo de compilación, mientras que en el tipo de enlace dinámico del objeto se determina en el tiempo de ejecución.
fuente
Porque el compilador conoce el enlace en tiempo de compilación. Si invoca un método en una interfaz, por ejemplo, el compilador no puede saberlo y el enlace se resuelve en tiempo de ejecución porque el objeto real que tiene un método invocado podría ser uno de varios. Por lo tanto, eso es tiempo de ejecución o enlace dinámico.
Su invocación está vinculada a la clase Animal en tiempo de compilación porque ha especificado el tipo. Si pasa esa variable a otro método en otro lugar, nadie sabría (aparte de usted porque lo escribió) qué clase real sería. La única pista es el tipo de animal declarado.
fuente