Почему в объекте переменные родителя

169
06 ноября 2021, 02:40

Был на тестировании по 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....

Соответственно вопрос: почему?

Answer 1

Это явление называется 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);
Answer 2

В отличие от методов переменные не переопределяются в подклассах, они затеняются. Есть такое понятие, как shadowing.

Когда вы создаете объект типа B, он содержит в себе как поле B.x, принадлежащее B, так и A.x, принадлежащее A. Только в A оно затенилось и его не видно из B, так как B имеет переменную с таким же именем. Единственный способ его увидеть, это обратиться к объекту с типом родительского объекта A, что вы и делаете:
System.out.println(a.x);
Потому что объект а был создан с типом A:
A a = new B();

READ ALSO
Всплывающая подсказка для JSpinner

Всплывающая подсказка для JSpinner

Я добавляю всплывающую подсказку для счетчика и хочу установить фиксированное местоположение для нееДелаю это так:

113
java: Как реализовать прием и передачу udp пакетов в разных потоках для параллельной работы?

java: Как реализовать прием и передачу udp пакетов в разных потоках для параллельной работы?

пишу приложение для android, при реализации, приведенной ниже, работает прием пакетов, но не работает отправкаесли убрать запуск потока для приема...

161
Проблемы в преобразовании данных в Java

Проблемы в преобразовании данных в Java

Начинаю разбираться в Java и у меня проблемы в преобразовании list в массив

113
Динамическая загрузка jar в JVM

Динамическая загрузка jar в JVM

Пытаюсь динамически загрузить файл в JVM при помощи ClassLoader

146