Здравствуйте! Столкнулся со странным поведением компилятора, объясните пожалуйста, почему происходит вывод разных строк.
class EntityModel{
public String name;
public EntityModel(){
this.name = "EntityModel";
}
public String getName(){
return this.name;
}
}
class Model1 extends EntityModel{
public String name;
public Model1(){
this.name = "Model1";
}
@Override
public String getName(){
return this.name;
}
}
Вызов:
EntityModel m = (EntityModel)new Model1();
System.out.println(m.name);
System.out.println(m.getName());
Вывод:
EntityModel
Model1
Код на ideone.com
Почему обращение к полю на прямую и через геттер дают разные результаты?
Ответ
Хе :) Если коротко, то в Java методы виртуальные, а поля — нет. То есть, привязка метода к имени метода производится на этапе выполнения в соответствии с настоящим, динамическим типом объекта, а вот привязка поля — статическая, производится на этапе компиляции. Так сделано потому, что выставлять наружу открытое поле всё равно очень плохая практика, поэтому доступ к полям можно ускорить за счёт точного определения поля во время компиляции. А вот вызывая публичный метод, программист не ожидает вызова не самого «свежего» метода, так что здесь логичнее виртуальный вызов. (Впрочем, архитекторы C# считают не так, но это уже вопрос дизайна языков.) Это всё ещё один аргумент к тому, чтобы делать все поля private, и получать доступ к ним лишь через getter.
Комментариев нет:
Отправить комментарий