Путаница с повышением и понижением в Java

Хорошо. Так что если...

int x=3;
int y=5;


x=y;

Получается x=5, верно?

Итак, если B является подклассом A...

A a=new A();
B b=new B();

a=b;

^^^Почему это считается преобразованием?

Разве «а» не должно стать «б», а не наоборот? Кто-нибудь может мне все это объяснить?


person ABCD123    schedule 29.09.2013    source источник


Ответы (4)


Вместо As и Bs давайте перейдем к конкретному примеру.

class Person {
    public void greet() {
        System.out.println("Hello there!");
    }
}

class ComputerScientist extends Person {    // Does he, really?
    @Override
    public void greet() {
        System.out.println("Hello there! I work at the Informatics Department.");
    }

    public void validateAlgorithm(Algorithm a)
            throws InvalidAlgorithmException {
        // ...
    }
}

Когда у вас есть ComputerScientist как

ComputerScientist cs = new ComputerScientist();

Вы можете получить доступ как к greet, так и к validateAlgorithm. Вы знаете, что он Person, и можете greet его/ее, как и любой другой человек. Однако вы также можете обращаться с ним/ней конкретно как с ComputerScientist.

Когда вы присваиваете этот объект переменной типа Person, все, что вы делаете, это говорите "Меня больше не волнует, что вы ComputerScientist. Отныне я буду относиться к вам так же, как к любому другому Person".

Person p = cs;

Что эквивалентно

Person p = (Person) cs;

Объект, на который ссылается p, все еще знает, как validateAlgorithm, и все еще говорит вам, что он (она) работает в отделе информатики. Однако при доступе к нему через p вы сообщаете компилятору, что хотите только greet это Person, и ничего больше.

Это называется восходящим преобразованием, потому что переменная поднимается вверх в дереве иерархии, где вверх означает более общий/абстрактный и вниз означает более конкретный. Вы обобщаете ComputerScientist как Person.

person afsantos    schedule 29.09.2013
comment
+!, хорошее объяснение :-) - person nIcE cOw; 29.09.2013

После a = b; переменная a (объявленная с типом A) будет ссылаться на объект типа B. Таким образом, присваивание включает неявное восходящее преобразование: a = (A)b;, преобразующее представление Java b из B в его суперкласс A. Это взлет.

person pts    schedule 29.09.2013
comment
Обратите внимание, что хотя объект, на который ссылается b, будет рассматриваться как A, после a = b указанный объект по-прежнему является B, он не преобразуется буквально. Например, все переопределенные методы остаются переопределенными. - person afsantos; 29.09.2013

A a = new A();
B b = new B();

Поток выглядит следующим образом:

  • Объект A создается с помощью new A() и НАЗНАЧАЕТСЯ для ссылки на переменную. Аналогично объект B создается с использованием new B() и НАЗНАЧАЕТСЯ для ссылки на переменную b
  • Здесь следует отметить, что оценка идет от правой стороны к левой, поэтому сначала вычисляется правая сторона, а результаты присваиваются соответствующим переменным.

Теперь перейдем к вашей проблеме, поэтому a=b является UPCASTING

  • Вышеупомянутые пункты применимы и к этому утверждению, сначала оценивается b, который является подклассом a. Теперь, поскольку вы назначаете подкласс суперклассу, происходит неявное приведение от подтипа к супертипу, что, конечно же, является UPCASTING.

Эта ссылка сделает его более понятным https://www.youtube.com/watch?v=Wh-WZXCAarY

Надеюсь это поможет.

person Abdullah Khan    schedule 14.03.2015

Это сделает х=5, верно?

Верно.

Итак, если B является подклассом A...

^^^Почему это считается преобразованием?

Потому что это то, что есть.

Разве «а» не должно стать «б», а не наоборот?

Да, и это так. Ссылка на B преобразуется в ссылку на 'A'.

person user207421    schedule 29.09.2013
comment
Это действительно отвечает на вопрос? ОП спрашивает, почему. Вы повторили то, что ОП уже знает. - person Suresh Atta; 29.09.2013