Наследование Java - унаследованные переменные «копируются» или кэшируются дочерним классом? - PullRequest
0 голосов
/ 29 октября 2019

Мне любопытно, почему последние два отпечатка генерировали разные значения?

class A {
    int i = 1212;
}

class B extends A {
    A a;

    public B(A a) {
        this.a = a;
    }
}

class MainClass {
    
    public static void main(String[] args) {
        A a = new A();

        B b = new B(a);

        System.out.println(a.i);

        System.out.println(b.i);

        System.out.println(b.a.i);

        b.a.i = 2121; 
        
        System.out.println("--------");

        System.out.println(a.i); // 2121 ??

        System.out.println(b.i); // 1212 ??
    }
}

Когда я устанавливаю «i» следующим образом:

 b.a.i = 2121; 

Я обращаюсь к той же ссылке, это означает, что тот же объект A? Объект A создается только один раз, поэтому то, как можно установить переменную для объекта и получить другой результат, зависит от способа, которым я получаю доступ к этому значению?

ОБНОВЛЕНИЕ: Отладка переменных в IntelliJ Debug snapshot

В IDE кажется, что у класса B есть своя собственная копия "i", которая, конечно, не трогается, если ее изменить с помощью "bai", потому что изменение было сделано в объекте A. Можете ли вы поспорить с этим предположением, потому что оно все еще в моей голове, и отладка IDE показывает мне, что в объекте "b" есть переменная "i".

Ответы [ 3 ]

2 голосов
/ 29 октября 2019

Здесь объявление B ссылается на объект A двумя различными способами

  1. , непосредственно наследуя A.
  2. сохраняя A как свойство.

Итак, у B два разных вопроса A.

. вы ссылаетесь на тот же A, что и наследующий ответ: нет, b.a.i вы не ссылаетесь на наследующее A, вы просто ссылаетесь на свойство A

объект A создается, если это правда частично, фактическивы создаете другой A, создавая объект B.

Чтобы обратиться к наследующему A, вы должны использовать b.i

1 голос
/ 29 октября 2019

Я хотел бы отметить одну вещь: это не типично расширять класс, а затем создавать ссылку на этот класс внутри дочернего класса.

Когда класс Bрасширяет класс A, это означает, что класс B уже имеет int i = 1212; . Когда вы расширяете класс, вы, по сути, строите поверх него.

Итак, в вашем случае, когда вы создаете новый A объект, i = 1212. А затем вы создаете новый B объект и передаете a, однако, поскольку класс B расширяет A, у него уже есть переменная с именем i , равная 1212.

Ваши операторы печати имеют смысл:

  • ai будет равно 1212, потому что это значение, установленное в классе A.
  • bi будет равно 1212, потому что B расширяет A и унаследует переменную i от класса A.
  • bai будет изначально равен 1212, потому что вы 1.) создали объект A a , 2.) создал объект B b , который имеет собственную переменную A Object, для которой вы установили a .
  • Когда вы звоните bai = 2121 , вы устанавливаете переменную вашего объекта B a , чтобы иметь i значение 2121. Но помните, что объектСсылка в вашем объекте B указывает на первый объект, который вы создали. И a и ba указывают на один и тот же объект в памяти.
1 голос
/ 29 октября 2019

Думаю, что int i = 1212 - это значение по умолчанию для всех экземпляров A или его дочерних элементов, когда вы изменили значение для b, вы измените его только для этого экземпляра. Таким образом, другие экземпляры сохраняют значение по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...