Немного о виртуальных методах в Java
Сегодня я хочу рассмотреть некоторые особенности переопределения методов в Java. В java нельзя переопределить:
- поля класса
- конструкторы, инициализаторы класса
- статические методы
- статические поля
Подробнее об этом можно прочитать в
Java Language Specification, §8.4.8Итак, в java все нестатические неприватные (то есть,
protected,
package и
public) методы являются виртуальными. Ключевое слово
final запрещает возможность дальнейшего переопределения метода в подклассах. Рассмотрим следующий пример:
public class A {
int i = 3;
int getI() {return i;}
}
public class B extends A{
int i = 5;
int getI() {return i;}
}
A a = new B();
System.out.println(a.i);
System.out.println(a.getI());
Вопрос: что выведет данный код?
Ответ:
- Так как поля класса не наследуются, то у класса A своё поле i и у класса B тоже своё поле i. Так как для полей полиморфизм не действует, то при обращении a.i мы обращаемся к классу A, поэтому на экран будет выведено 3.
- При вызове метода a.getI() у нас в дело вступает полиморфизм, поэтому будет вызван метод от класса, инстанс которого был создан. Соответственно, мы получим на выходе 5.
Другой пример:
public class A {
static int i = 3;
static int getI() {return i;}
}
public class B extends A{
static int i = 5;
static int getI() {return i;}
}
A a = new B();
System.out.println(a.i);
System.out.println(a.getI());
Статические поля и методы виртуальными не являются, поэтому оба вызова выведут нам 3.