Был на тестировании по Java и столкнулся со следующей задачей.
package com.test;
import java.util.*;
public class Test {
public static void main(String[] args) {
A a = new B();
B b = new B();
System.out.println(a.x);
System.out.println(b.x);
}
}
class A {
int x = 1;
A() {
this.x = 2;
System.out.println("Зашли в конструктор A");
System.out.println(this.x);
}
}
class B extends A {
int x = 3;
B() {
this.x = 4;
System.out.println("Зашли в конструктор B");
System.out.println(this.x);
}
}
В консоли, внезапно, следующее:
Зашли в конструктор A
2
Зашли в конструктор B
4
Зашли в конструктор A
2
Зашли в конструктор B
4
2
4
Переменные, насколько я понимаю относятся к объекту, а не к ссылке. более того, я еще мог бы сам себе это объяснить, если бы не задал бы явно в конструкторе this.x=, мол возможно действительно переменная обносится к ссылке и храниться вообще в стеке а не в куче, но тут явно используется конструктор от класса B....
Соответственно вопрос: почему?
Это явление называется shadowing.
x в A и x в B - это разные переменные. Когда Вы обращаетесь к a.x, это x из A, так как тип a - A. Что бы получить доступ к B.x из ссылки a, надо сделать ((B)a).x.
Если Вы хотите, чтобы это была одна и та же переменная, закомментируйте int x; в классе B.
Для интереса, добавьте в конструктор B:
System.out.println(((A)this).x);
В отличие от методов переменные не переопределяются в подклассах, они затеняются. Есть такое понятие, как shadowing.
Когда вы создаете объект типа B, он содержит в себе как поле B.x, принадлежащее B, так и A.x, принадлежащее A. Только в A оно затенилось и его не видно из B, так как B имеет переменную с таким же именем. Единственный способ его увидеть, это обратиться к объекту с типом родительского объекта A, что вы и делаете:
System.out.println(a.x);
Потому что объект а был создан с типом A:
A a = new B();
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости