¿Cómo funciona el trabajo polimorfismo en Java para este caso general (método con parámetros)?

CandyCrusher:

Tengo el código para un caso general:

public class A {
    public String show(A obj) {
        return ("A and A");
    }
}

public class B extends A {
    public String show(B obj) {
        return ("B and B");
    }

    public String show(A obj) {
        return ("B and A");
    }
}

public class C extends B {

}

public class Test {
    public static void main(String[] args) {
        A a = new B();
        B b = new B();
        C c = new C();

        System.out.println("1--" + a.show(b));
        System.out.println("2--" + a.show(c));     
    }
}

Los resultados son los siguientes:

1--B and A
2--B and A

Sé que es una cadena de prioridad de mayor a menor en Java:

this.show(O), super.show(O), this.show((super)O), super.show((super)O)

Mi entendimiento es a continuación:

En este código:

A a = new B()

Una conversión hacia arriba pasa. A es una referencia de la clase padre y B es una referencia de la clase padre del niño. Cuando el código se compila y ejecuta, la referencia de la clase padre del niño determina cómo se elige el método. En este caso, show(A)en la clase B se elige.

También hay un requisito de que el polimorfismo tiene que cumplir: El método que se elija debe ser incluido en la definición de la clase padre.

Podría alguien dar una explicación más detallada sobre el resultado que se muestra?

TiiJ7:

Con el fin de conseguir por la que recibe el resultado B and Ados veces, lo que necesita saber que hay 2 partes en este: compilación y tiempo de ejecución.

Compilacion

Al encontrarse con la declaración a.show(b), el compilador toma estos pasos básicos:

  1. Mirar el objeto de que el método se llama en ( a) y obtener su tipo declarado. Este tipo es A.
  2. En la clase Ay todos sus tipos súper, hacer una lista de todos los métodos que se denominan show. El compilador sólo encontrará show(A). No se parece a ningún método en Bo C.
  3. En la lista de los métodos que se encuentran, elegir el que mejor se ajuste a los parámetros ( b) si los hubiere. show(A)aceptará b, por lo que se elige este método.

Lo mismo sucederá en la segunda convocatoria donde se pasa c. Los dos primeros pasos son los mismos, y el tercer paso se encuentran de nuevo show(A)ya que sólo hay uno, y que también coincide con el parámetro c. Así que, por tanto de las llamadas, el resto del proceso es el mismo.

Una vez que el compilador ha descubierto qué método se necesita, se creará una instrucción de código de bytes invokevirtual, y poner el método de resolver show(A)como el que se debe llamar al teléfono (como se muestra en Eclipse mediante la apertura de la .class):

invokevirtual org.example.A.show(org.example.A) : java.lang.String [35]

Tiempo de ejecución

El tiempo de ejecución, cuando finalmente llega a las invokevirtualnecesidades de hacer unos pasos también.

  1. Obtener el objeto sobre el que se llama al método (que ya está en la pila para entonces), que es a.
  2. Mira el actual tiempo de ejecución tipo de este objeto. Puesto que a = new B(), este tipo es B.
  3. Busque en By tratar de encontrar el método show(A). Este método se encuentra ya Bredefine. Si esto no hubiera sido el caso, se vería en las clases super ( Ay Object) hasta que se encuentre un procedimiento de este tipo. Es importante tener en cuenta que sólo tiene en cuenta show(A)los métodos, así por ejemplo. show(B)de Bque nunca se considera.
  4. El tiempo de ejecución ahora llamar al método show(A)de B, dando la String B and Acomo resultado.

Más detalles sobre esto se da en la especificación deinvokevirtual :

Si el método no es resuelta firma polimórfico (§2.9), entonces la instrucción invokevirtual procede de la siguiente manera.

Sea C la clase de ObjectRef. El método actual para ser invocada se selecciona por el siguiente procedimiento de búsqueda:

Si C contiene una declaración para un método de instancia m que anula (§5.4.5) el método resuelto, entonces m es el método a invocar, y las termina procedimiento de búsqueda.

De lo contrario, si C tiene una superclase, este mismo procedimiento de búsqueda se realiza de forma recursiva utilizando la superclase directa de C; el método que se invoca es el resultado de la invocación recursiva de este procedimiento de búsqueda.

De lo contrario, se produce un AbstractMethodError.

Para su ejemplo, el objectrefdecir a, su clase es By el método de resolver es el de la invokevirtual( show(A)de A)


tl: dr - tiempo de compilación determina qué método de llamada, tiempo de ejecución determina dónde llamar desde.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=192202&siteId=1
Recomendado
Clasificación