21 July, 2011

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

1 comment: