2017-01-08 6 views
0

Скажите, что у вас есть массив Список объектов ArrayList<Object> arr = new ArrayList<Object>();, и вы затем заполняете этот arraylist несколькими разными объектами, все из которых наследуются от object.Как работает динамический (run-time) полиморфизм в java? Другими словами, как JVM знает, какие методы вызывать?

arr.add(new Integer(1)); 
arr.add("Im a String"); 
arr.add(new SomeOtherObject); 

Допустим, вы затем цикл через ArrayList, вызывающего метод .toString(), это действительно будет работать, как и ожидалось, вызывая переопределены toString() методы в String и Integer классов, то, что меня смущает, что в JVM, то Integer и String объекты внутри массиваList были неявно заброшены в объекты, так как в мире JVM знает, кастовать их обратно во все, что было до того, как они были помещены в массивList? Извините, если у этого вопроса есть очевидный ответ, но это, похоже, не имеет для меня никакого смысла.

+0

Casting не преобразование, за исключением случая примитивных типов. – EJP

ответ

4

Каждый объект имеет свой тип, хранящийся в заголовке этого объекта. Когда вы передаете ссылку на объект, это никак не изменяет объект.

Например, при вызове .toString он просматривает метод вызова из описания классов. ПРИМЕЧАНИЕ. Он не должен делать это каждый раз, если он может оптимизировать код.

1

Предположим, у вас есть Fooclass, и у вас есть ArrayList<Object> под названием arr. Когда вы скажете arr.add(new Foo()), новый объект Fooclass добавлен в arr в качестве нового элемента. Это возможно, так как Foo является class и наследуется от Object. Однако объект является Foo, хотя Foo унаследован от Object. Следовательно, когда вы вызываете его toString, он вызывается toString объекта Foo, который вы создали.

Предположим, у вас есть список массивов Bird s и Eagle s fly красиво. Итак, если вы вызываете метод fly()Bird, который на самом деле является Eagle, он будет летать красиво. Это на самом деле большая особенность наследования, и это имеет очень большой смысл.

1

По правде говоря, JVM не знает, как вернуть их в исходное. Мы должны будем выполнить эту задачу для этого. Рассмотрим это ... (после ваших строк кода)

SomeOtherObject obj = arr.get(2); //trying to access the third element 

Вы обязательно получите ошибку во время компиляции. Теперь попробуйте явно передать возвращенный объект.

SomeOtherObject obj = (SomeOtherObject)arr.get(2); 

Это работает отлично! Зачем? Потому что объект, возвращаемый методом get(), был совместим с типом, который он выполнял.

Теперь рассмотрим это также (я знаю, что я не могу этого сделать), просто для проверки того, может ли JVM сказать нам, какой именно объект.

SomeOtherObject obj = (SomeOtherObject)arr.get(1); //1 instead of 2 

Да, да, я знаю, что второй член этого массива является строкой, и я не могу этого сделать. Но давайте посмотрим, что должен сказать JVM (хотя ошибка компилятора отсутствует). Сообщение, которое мы получаем, состоит в том, что объект не может быть передан указанному типу. (Но мы не получаем точный тип объекта).

Вы поняли? JVM здесь знает только, что объекты, передаваемые этому массиву, являются объектами, совместимыми с Object. Он не имеет понятия, действительно ли мы передали String, int (или, скорее, Integer, потому что примитивы не могут быть сохранены в коллекциях) или SomeOtherObject (любой класс, определенный в Java, является непосредственным подклассом Object).

Теперь, чтобы ответить на ваш вопрос:

  1. (Как я смог получить строку и Integer обратно в нормальное (хотя я все равно придется вводить отливка их)) Причина в том, что строки и классы-оболочки (Integer - это класс-оболочка) переопределили метод toString(), унаследованный от Object. Поэтому печать этих объектов дает фактическое значение.

  2. (Как JVM знает, какой тип их отличает) JVM на самом деле не знает, какой объект должен быть преобразован в какой тип перед возвратом пользователю. Он вернет только экземпляр объекта (это то, что JVM знает об объекте). Мы должны будем явно привести его к соответствующему типу.

Надеюсь, я ответил на ваш вопрос. Дайте мне знать, если это неясно.

Подробное описание о времени выполнения полиморфизм (ваш заголовок вопроса) дается на этом сайте: http://www.javatpoint.com/runtime-polymorphism-in-java

Смежные вопросы