Это динамическая отправка? - PullRequest
3 голосов
/ 20 августа 2011

Является ли эта динамическая отправка:

abstract class A{
    public method Meth1(){
    //somecode
    }
}

class B extends A{
}

class C extends A{
}

В другом классе полностью:

Some_Method(A a){
    a.Meth1();
}

Я не уверен, что это динамическая отправка, потому что поведение одинаково в обоих подклассах?

Если это не так, будет ли динамическая отправка, если поведение определено для подклассов?

Ответы [ 4 ]

1 голос
/ 20 августа 2011

Я не уверен, что вы говорите о своем конкретном вопросе (может быть некоторая оптимизация, специфичная для реализации, которая обойдёт проверку типов во время выполнения, если статически известно, что вызванный метод объявлен только в одном классе), но, действительно, динамическая диспетчеризация позволяет определить фактическую реализацию метода Meth1 во время выполнения. Таким образом, даже если сейчас ни B, ни C не переопределяют Meth1, позже, если переопределено, динамическая диспетчеризация обеспечит, что если тип времени выполнения формального параметра a равен B, то фактическая реализация будет что на B. Аналогично в случае C.

Сравните это с перегрузкой метода в Java, где фактический метод определяется во время компиляции на основе объявленного типа используемых аргументов.

public class Overloading {

  public static class User {}
  public static class Admin extends User {}

  public static String foo(User user) {
    return "User specific method";
  }

  public static String foo(Admin admin) {
    return "Admin specific method";
  }

  // This will print "User specific method" two times, because both
  // user1 and user2 have same compile time type, i.e., User. Runtime
  // type does not matter.
  public static void main(String[] args) {
    User user1 = new User();
    System.out.println(foo(user1));

    User user2 = new Admin();
    System.out.println(foo(user2));
  }
}
0 голосов
/ 07 мая 2016

Да, это так!

Поскольку в Java все методы экземпляров по умолчанию являются виртуальными.( Можете ли вы написать виртуальные функции / методы на Java? )

Затем необходимо выполнить a.Meth1 () во время выполнения.Помните, что вы можете динамически загружать новый JAR с классом, производным от которого есть переопределение этого метода.

0 голосов
/ 11 июля 2014

Это динамическая отправка, потому что компилятор не может предположить, что при создании байт-кода для вызывающего класса он знает полную вселенную классов.

Ни интерпретатор байт-кода, ни JIT-компилятор не будут работать во время выполнения, хотя бы потому, что классы могли загружаться динамически.

На мой взгляд, это не оставляет java никакой другой опции, кроме как использовать динамическую диспетчеризацию, а не «вырезать углы», т.е. оптимизировать вызовы в вызовы базового класса.

0 голосов
/ 20 августа 2011

Динамическая отправка - это когда реализация метода выбирается на основе фактического, а не объявленного типа. Java не поддерживает динамическую диспетчеризацию, кроме как через отражение. Это статически типизированная полиморфная отправка.

Если у вас загружена одна реализация, JVM применит моморфную оптимизацию (получая очень быстрые вызовы), которая будет отменена, когда JVM увидит, что вторая реализация передана тому же коду.

Возможно, вы слышали о новом байт-коде invokedynamic, который реализует динамическую диспетчеризацию в JVM, но он предназначен для использования другими языками JVM, и программы Java не будут использовать его, кроме случаев, когда выполняется генерация байт-кода.

[Edit] Вот простой пример:

Collection<Integer> c = new ArrayList<Integer>(Arrays.asList(2, 1, 0));
c.remove(2); // Collection.remove(E element) or List.remove(int idx)?
assert c.equals(Arrays.asList(1, 0)); // passes in case of static dispatch
assert c.equals(Arrays.asList(2, 1)); // fails - would pass in case of dynamic dispatch
...