这是动态调度:
abstract class A{
public method Meth1(){
//somecode
}
}
class B extends A{
}
class C extends A{
}
完全在另一个班级:
Some_Method(A a){
a.Meth1();
}
我不确定这是否是动态调度,因为两个子类的行为相同?
如果不是,如果行为是根据子类定义的,它会是动态调度吗?
这是动态调度:
abstract class A{
public method Meth1(){
//somecode
}
}
class B extends A{
}
class C extends A{
}
完全在另一个班级:
Some_Method(A a){
a.Meth1();
}
我不确定这是否是动态调度,因为两个子类的行为相同?
如果不是,如果行为是根据子类定义的,它会是动态调度吗?
我不确定您对特定问题的看法(如果静态地知道调用的方法仅在一个类中声明,则可能会有一些特定于实现的优化将绕过运行时类型检查),但实际上,动态调度允许方法的实际实现Meth1
要在运行时确定。因此,即使现在,既不覆盖B
也不C
覆盖Meth1
,以后,如果覆盖,动态调度将确保如果形式参数的运行时类型a
是B
,那么实际实现将是 on 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));
}
}
It is dynamic dispatch because the compiler cannot assume, when producing bytecode for the calling class, that it knows the full universe of classes.
Neither will the bytecode interpreter or the JIT compiler at runtime, at least because classes could be loaded dynamically.
In my view, this leaves java no other option than use dynamic dispatch, and not 'cut corners' i.e. optimise calls into base class calls.
是的!。
因为在 Java 中,所有实例方法默认都是虚拟的。(你能用Java写虚函数/方法吗?)
然后解析 a.Meth1() 需要在运行时完成。请记住,您可以使用从 A 派生并覆盖该方法的类动态加载新 JAR。
动态分派是根据实际而不是声明的类型选择方法实现。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