Java是否支持动态方法调用?

Laz*_*zer 3 java bytecode dynamic dynamic-method

class A           { void F() { System.out.println("a"); }}
class B extends A { void F() { System.out.println("b"); }}

public class X {
    public static void main(String[] args) {
        A objA = new B();
        objA.F();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里F()是动态调用的,不是吗?

这篇文章说:

... Java字节码不支持动态方法调用.有三种受支持的调用模式:invokestatic,invokespecial,invokeinterface或invokevirtual.这些模式允许调用具有已知签名的方法.我们谈论强类型语言.这允许在编译时直接进行一些检查.

另一方面,动态语言使用动态类型.所以我们可以在编译时调用一个未知的方法,但是使用Java字节码完全不可能.

我错过了什么?

Jac*_*ack 13

你混淆了动态调用动态绑定 ..

第一个允许类型检查器接受程序,在这些程序中,您不确定某个方法是否会在运行时出现在对象上,而动态绑定只是根据对象的运行时类型选择正确的实现但是静态维护类型检查.

这是什么意思?

这意味着在您的示例中,Java将调用对象上的实现,B因为objA变量的运行时类型是B; 它会编译因为它知道a B 是一个 A所以方法调用在运行时不会失败(肯定objA会有一个F实现).

使用动态调用时,它不会在编译时检查您调用的对象的类型是否F包含该方法,当然,如果在执行期间该方法在指定对象上不可用,则会引发异常.

只是为了琐事:该invokedynamic功能将添加到Java7中,因为许多脚本语言已编写为在JVM之上工作,缺乏动态调用功能迫使这些语言的开发人员在脚本和真实JVM之间添加中间层关心使用反射进行动态调用.当然这种方法会带来很多开销(想想Grovvy的MetaClass),这就是为什么Sun决定给他们一个帮助.