Почему объектный класс Java остается таким же после литья?

Я попытался поднять объект. Но во время выполнения объектный класс остается производным классом.

Derived drv = new Derived();

Base base = (Base) drv;

System.out.println("Class : " + base.getClass()); 

//prints -> Class : class packagename.Derived

Итак, почему свойство класса не изменилось?


person Huseyin    schedule 18.03.2014    source источник
comment
Я сделал пример на ideone, чтобы вы поиграли с этой концепцией, но слишком поздно. Ответ Ти Джея правильный.   -  person 2rs2ts    schedule 18.03.2014
comment
@ 2rs2ts: Спасибо, я добавил его в свой ответ, очень признателен.   -  person T.J. Crowder    schedule 18.03.2014


Ответы (3)


Итак, почему свойство класса не изменилось?

Поскольку объект не изменился, только тип ссылки на него. Кастинг вообще не влияет на сам объект.

В Java, в отличие от некоторых других языков (к счастью), тип ссылки в значительной степени не влияет на то, какую версию метода вы получите. Например, рассмотрим эти два класса (спасибо 2rs2ts!):

class Base {
    public Base() {}
    public void foo() {
        System.out.println("I'm the base!");
    }
}

class Child extends Base {
    public Child() {}
    public void foo() {
        System.out.println("I'm the child!");
    }
}

Этот код:

Child x = new Child();
Base y = (Base) x;
y.foo();

... выходы

I'm the child!

потому что даже несмотря на то, что тип y Base, объект, который мы вызываем foo, является Child, и поэтому вызывается Child#foo. Здесь (снова любезно предоставлено 2rs2ts) пример на ideone для игры.

Тот факт, что мы получаем Child#foo, несмотря на прохождение Base ссылки, имеет решающее значение для полиморфизма.

Так уж случилось, что метод, который вы вызывали (getClass), может только быть Object#getClass, потому что это метод final (подклассы не могут его переопределить). Но концепция имеет решающее значение, и я подумал, что это, вероятно, суть того, о чем вы спрашивали.

Главное, что делает тип ссылки - определяет, к каким аспектам объекта вам разрешен доступ. Например, предположим, что мы добавляем bar к Child:

class Child extends Base {
    public Child() {}
    public void foo() {
        System.out.println("I'm the child!");
    }
    public void bar() {
        System.out.println("I'm Child#bar");
    }
}

Этот код не компилируется:

Child x = new Child();
Base y = (Base) x;
y.bar(); // <=== Compilation error

... потому что Base не имеет bar метода, и поэтому мы не можем получить доступ к bar методу объекта через ссылку с типом Base.

person T.J. Crowder    schedule 18.03.2014
comment
Base base = (Base) drv; не конвертирует объект типа Derived, на который указывает drv, в < b> Объект базового типа. Он просто заявляет, что объект типа Derived может обрабатываться как объект типа Base и может выполнять все, что Base < / b> -тип объект может. - person NoName; 21.06.2017
comment
@NoName: слово преобразовать нигде в ответе не встречается. - person T.J. Crowder; 21.06.2017
comment
@ T.J. Краудер: Ой, возможно, вы неправильно поняли мой комментарий как поправку к вашему ответу. Я просто пытаюсь прояснить образ мышления актеров. - person NoName; 21.06.2017
comment
@NoName: Хорошо. Мне показалось, что я достаточно хорошо рассмотрел это в собственном ответе. - person T.J. Crowder; 22.06.2017

Вы не можете изменить тип экземпляра в Java. Все, что вы делаете со своим приведением, - это ссылаетесь на него из переменной другого типа.

person Andres    schedule 18.03.2014
comment
Вы имеете в виду ... тип объекта ...? Экземпляр - это ссылочная переменная, указывающая на объект. - person NoName; 21.06.2017

Повышение не меняет тип объекта. Собственно говоря, НИЧТО не меняет тип объекта Java.

Это самая суть объектно-ориентированного программирования: объект имеет определенное поведение, на которое нельзя повлиять извне.

person Ray    schedule 18.03.2014
comment
An object has a defined behavior that can't be influenced from the outside. Не совсем :) - person Marko Topolnik; 18.03.2014
comment
Ладно, это не может быть ПЕРЕПРЕЩЕНО или обойти извне. Лучше? - person Ray; 18.03.2014
comment
Намерения, стоящие за ООП, - это одно; Семантика Java совсем другая. В частности, приведение ссылок не имеет ничего общего с определенным поведением объектов. Речь идет о ссылках по сравнению с объектами. - person Marko Topolnik; 18.03.2014
comment
@ T.J. Краудер: Нет, здесь мы говорим о повышении качества: forum.codecall.net/ topic / 50451-upcasting-downcasting - person Ray; 18.03.2014
comment
@Marko Topolnik Изначально вопрос был в том, почему приведение не повлияло на результат getClass (). Это связано с поведением объекта, не так ли? - person Ray; 18.03.2014
comment
Вопрос может быть в поведении, но не в ответе. Если у класса есть общедоступное поле, названное так же, как поле в его суперклассе, то восходящее преобразование изменит результат. Объяснение этого пустым высказыванием, таким как ваше, не имеет обучающей ценности. - person Marko Topolnik; 18.03.2014
comment
@Ray: Спасибо, очень признателен. - person T.J. Crowder; 18.03.2014