Oleg Atamanenko

thoughts about programming

Немного о виртуальных методах в 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());

Вопрос: что выведет данный код?
Ответ:

  1. Так как поля класса не наследуются, то у класса A своё поле i и у класса B тоже своё поле i. Так как для полей полиморфизм не действует, то при обращении a.i мы обращаемся к классу A, поэтому на экран будет выведено 3.
  2. При вызове метода 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.