Это динамическая отправка?

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

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

class B extends A{
}

class C extends A{
}

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

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

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

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

4 ответа

Я не уверен, что вы говорите о своем конкретном вопросе (может быть некоторая оптимизация, специфичная для реализации, которая обойдёт проверку типов во время выполнения, если статически известно, что вызванный метод объявлен только в одном классе), но, действительно, динамическая диспетчеризация позволяет фактическая реализация 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));
  }
}

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

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

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

Да, это!.

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

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

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

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

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

[Править] Вот простой пример:

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
Другие вопросы по тегам