por qué la variable de instancia de superclase no se anula en el método de clase secundaria

¿Por qué la variable de instancia de superclase no se anula en el método de subclase? Vea mi código a continuación … en qué método se anula la impresión, pero la variable a no. y por qué el código permite escribir variables duplicadas en la subclase.

class B { int a=10; public void print() { System.out.println("inside B super class"); } } class C extends B { int a=20; public void print() { System.out.println("inside C sub class"); } } public class A { public static void main(String[] args) { B b=new C(); b.print();//it will print inside c sub class System.out.println(ba);//it will print super class variable value=10 } } 

¿Por qué la variable de instancia de superclase no se anula en el método de subclase? Vea mi código a continuación …

Porque las variables de instancia NO PUEDEN anularse en Java 1 . En Java, solo se pueden anular los métodos.

Cuando declara un campo con el mismo nombre que un campo existente en una superclase, el nuevo campo oculta el campo existente. El campo existente de la superclase todavía está presente en la subclase, e incluso se puede usar … sujeto a las reglas normales de acceso de Java.


1 – ¿Por qué? 1) Debido a que la anulación de variables rompe la abstracción de clase. Por ejemplo, si una anulación cambia el tipo de la variable, es probable que cambie (rompa) el comportamiento de los métodos en la clase principal que usó la variable original. 2) Porque no lograría nada que no se pueda hacer de otras maneras … mejor. Por ejemplo, un buen diseño declara todas las variables de instancia como privadas y proporciona getters / setters para ellas según sea necesario. Los getters / setters pueden anularse, y la clase padre puede “protegerse” contra anulaciones indeseables al usar los campos privados directamente, o declarar los getters / setters final .

Referencias

  • Tutorial de Java – Ocultar campos
  • JLS Ejemplo 8.3.1.1-3 – Ocultamiento de campos de instancia .

Puede consultar la siguiente sección / ejemplos en la especificación del lenguaje Java que explica sobre el tema.

  1. Ejemplo 8.3.1.1-3. Ocultación de variables de instancia
  2. Sección 8.4.8. Herencia, anulación y ocultamiento y ejemplos relacionados

El rest de mi publicación es una información adicional para aquellos que estén interesados ​​en rascar la superficie de jvm internals en este tema. Podemos comenzar examinando los códigos de bytes generados para la clase A usando javap. A continuación, se desintegran los códigos de bytes en unas instrucciones basadas en texto legibles por humanos (mnemónicos).

 javap -c A.class 

Sin perdernos en muchos detalles de todo el ensamblaje, podemos enfocarnos en las líneas correspondientes a b.print y ba

 9: invokevirtual #4 // Method B.print:()V ... ... 16: getfield #6 // Field Ba:I 

Inmediatamente podemos inferir que los códigos op utilizados para acceder al método y a una variable son diferentes. Si eres de una escuela C ++, puedes sentir que todas las llamadas a métodos son virtuales por defecto en java.

Ahora escribamos otra clase A1 idéntica a A, pero solo tenemos un molde para acceder a la variable ‘a’ en C.

clase pública A1 {
public static void main (String [] args) {
B b = nuevo C ();
b.print (); // la conversión es irrelevante porque los métodos están enlazados de todos modos en el tiempo de ejecución System.out.println (((C) b) .a); // la conversión nos permite acceder al valor de a en C
}
}

Comstack el archivo y desmonta la clase.

javap -c A1.class

Notarías que el desarmado ahora apunta a Ca en lugar de Ba

19: getfield # 6 // Campo Ca: I

Si desea profundizar en esto, aquí va información adicional:
– invokevirtual corresponde al código de operación 0xb6
– getfield corresponde al código de operación 0xb4

Puede encontrar una especificación de JVM que explique exhaustivamente estos códigos de operación en: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html
Consulte en amazon.com los libros de “Máquina virtual Java” que podrían simplificar la vida útil de la desencoding de la especificación.

He modificado su código para una Explicación fácil, en lugar de la variable ‘a’, digamos que la Clase C contiene la variable ‘c’. Es por la misma razón por la cual la clase C no puede acceder a la variable de instancia de la Clase c en sí misma sin Typecasting. Ejemplo dado a continuación

 class B { int a=10; public void print() { System.out.println("inside B super class"); } } class C extends B { int x=20; public void print() { System.out.println("inside C sub class"); } } public class A { public static void main(String[] args) { B b=new C(); System.out.println(bx);//will throw compile error unless b is type casted to Class C } } 

Entonces, en java, el comstackdor pasa por la referencia, no por la instancia. Para superar este comstackdor usa el polymorphism Runtime , pero es para los métodos, no para las variables de instancia. Por lo tanto, no se puede acceder a las variables sin el método de conversión de tipos y los métodos a menos que, anulados (polimoprismo de tiempo de ejecución), no se pueda acceder sin conversión de tipos.

Entonces, en nuestro caso, es obvio para la refrencia de Superclass que lleva una instancia de subclase, para ver en la superclase.

Como las variables de instancia no se anulan en Java, no hay un polymorphism de tiempo de ejecución asociado a ellas y, por lo tanto, en el momento de la comstackción solo se decide por referencia.

En tu código

 B b = new C(); b.print(); As b is of type Class B which is Parent to C and hence as there is no run time polymorphism it is decided at compile time to call instance variable of Class B. 

Aquí está mi perspectiva a nivel de diseño / conceptual sobre por qué las variables de instancia no se anulan. Para simplificar, si consideramos las clases abstractas, definen métodos abstractos y esperan que se anulen. Nunca ha habido nada como variables abstractas . Si lo hubo, entonces podríamos esperar que el lenguaje lo respaldara anulando. Entonces, cuando se diseña una clase abstracta, el diseñador define un estado concreto común y un comportamiento común (incluidos los métodos abstractos) para los subtipos. Casi siempre, si el estado se va a heredar (acceso protegido), entonces simplemente se heredará y creo que en muy pocos casos parte de él podría redefinirse, pero muy raramente volver a declararse. Por lo tanto, se espera que el estado sea simplemente heredado, mientras que se espera que el comportamiento se herede y se anule.