java - para - Array principiante de la confusión de objetos
curso de java para principiantes completo 40/40 español (3)
Esta es una de esas cosas extrañas que Java le permite hacer, asignando una matriz de una clase derivada a una variable de la clase base.
En su código, x
en tiempo de compilación es de tipo Type1[]
. Eso es lo que el compilador piensa que es. En tiempo de ejecución, x
es de tipo Type2[]
, pero el compilador no lo sabe.
El primer error se produce en el tiempo de ejecución porque, como dijo, no puede asignar Type1
a una variable de tipo Type2
.
Pero el segundo error ocurre en tiempo de compilación porque el compilador aún piensa que x
es de tipo Type1
, y no hay un método llamado method2
en Type1
, aunque x
realmente tenga un Type2[]
en tiempo de ejecución.
Para llamar a method2
, debe decirle al compilador que x[1]
es de tipo Type2
al lanzar:
((Type2)x[1]).method2();
¿Lección del día? No hagas esto:
Superclass[] array = new Subclass[2];
Te metes en problemas.
Tengo problemas para entender lo que realmente sucede cuando declaro la matriz en el siguiente código.
class Type1 {
}
class Type2 extends Type1 {
public void method2() {
}
}
class Test {
public static void main(String[] args) {
Type1[] x = new Type2[2];
x[0] = new Type1(); // runtime error
x[1] = new Type2();
x[1].method2(); // syntax error
}
}
Pensé que ya que el lado derecho de la declaración de la matriz es un new Type2[2]
que la matriz consistiría de variables de referencia del tipo Type2
. Si esto es cierto, el primer error tiene sentido porque no puedo tener un subtipo que se refiera a un supertipo.
Sin embargo, ¿por qué ocurre el segundo error dos líneas después de eso? ¿El method2()
no es conocido por Type2, por lo que el método es conocido por la variable de referencia? Parece que se debe a que Type1
no conoce el method2
, por lo que significa que la matriz se compone de variables de referencia del tipo Type1
. Si esto es cierto, ¿por qué ocurre el primer error ya que ya no es un subtipo que se refiere a un supertipo?
Además, ¿por qué el primer error es un error de tiempo de ejecución mientras que el otro es un error de sintaxis?
Tenga en cuenta que solo estoy en mi segundo curso de programación, por lo que mi terminología puede estar un poco fuera de lugar.
Edición: la pregunta here no responde a mi pregunta porque no responde por qué un elemento de una matriz como x
no puede invocar a method2()
aunque sea un elemento de x
de Type 2
. Mi pregunta es diferente debido a esto y porque también pregunta por qué ocurre el primer error cuando también ocurre el segundo error (por qué un elemento de x
no puede referirse y un objeto del tipo Type1
y al mismo tiempo no puede invocar method2()
) . Originalmente pensé que si ocurría un error, el otro no puede ocurrir. Quería una comparación entre los dos errores y una explicación más profunda que simplemente las reglas del polimorfismo.
Una referencia de supertipo puede referirse a un subtipo. Creo que entiendes esto, ya que el primer error es coherente para ti.
El segundo error se deriva del hecho de que en el momento de la compilación, x
sigue siendo un Type1[]
. Esto significa que, en tiempo de ejecución, la referencia puede contener cualquier subtipo, incluido un tipo que no tenga el método method2
. Es por eso que solo puede usar los métodos definidos en Type1
.
Por ejemplo, podría verificar si el tipo es en realidad Type2
en el tiempo de ejecución usando isInstanceOf
, y luego convertirlo en un Type2
y luego usar method2
. Sin embargo, generalmente hay mejores soluciones.
para ponerlo en términos sencillos para el siguiente código,
Type1[] x = new Type2[2];
solo tomemos Type1 x = new Type2;
no matrices, solo clases.
¿Qué inferiste del paso anterior?
Aquí x es una variable de referencia. Estamos creando un objeto de "Type2" y x tiene la referencia del Object Type2 [digamos, x es un control remoto que apunta al objeto Type2] . No olvide que, x es del tipo ''Type1'', lo que significa que no tiene un botón ''method2 ()'' en su control remoto. [Recuerde, method2 es de Type2 Class no Type1].
El compilador llama a un método en un objeto, solo cuando lo ve dentro de la clase. al compilador no le importa qué Objeto está creando [ aquí : nuevo Tipo2], todo lo que importa es en quién hace la llamada ( aquí: x [1], que es de tipo Tipo1 ). Por lo tanto, arroja el error de tiempo de compilación. No importa lo que suceda en el tiempo de ejecución o a qué objeto está apuntando, todo lo que le importa es si el tipo de referencia tiene o no el método de llamada [ En Nuestra terminología, ¿el control remoto tiene ese botón ]? .
¿Por qué el primer error es un error de tiempo de ejecución mientras que el otro es un error de sintaxis?
Espero que la explicación anterior, ( cuando considere los tipos de Array según su pregunta ) responda a su segunda mitad de la pregunta.
Y, en cuanto a la primera parte , prácticamente la respondiste. De todos modos, cosa que Arrays permite este tipo de cosas y explota en Runtime, mientras que Arraylist lo hace en tiempo de compilación. [Eso es parte de los genéricos].
Como dijiste, eres nuevo en esto, aquí está mi referencia para ti.
Referencia:
Head First Java