java 方法绑定,Java中的方法绑定

When I was reading Thinking in Java (4th Edition) recently, I got a problem about method binding in Java. First let's look at two definitions from the book:

Connecting a method call to a method body is called binding.

All method binding in Java uses late binding unless the method is static or final.

you can find those definitions in section Method-call binding from chapter Polymorphism. (page 281-282)

To testify that, I wrote the following code:

public class Test3{

public static void main(String[] args) {

BindingTest_Sub sub1 = new BindingTest_Sub();

BindingTest_Base sub2 = new BindingTest_Sub();

sub1.ovrLd(new Integer(1)); // statement 1

sub2.ovrLd(new Integer(2)); // statement 2

sub2.ovrRd(); // statement 3

}

}

class BindingTest_Base {

void ovrLd(Object obj){

System.out.println("BindingTest_Base ovrLd()");

}

void ovrRd(){

System.out.println("BindingTest_Base ovrRd()");

}

}

class BindingTest_Sub extends BindingTest_Base{

void ovrLd(Integer i){

System.out.println("BindingTest_Sub ovrLd()");

}

void ovrRd(){

System.out.println("BindingTest_Sub ovrRd()");

}

}

The execution result is:

BindingTest_Sub ovrLd()

BindingTest_Base ovrLd()

BindingTest_Sub ovrRd()

Based on this result, I have following questions:

According to the definition from the book, since all of my methods are inheritable, Java will use late binding (dynamic binding) for all three statements. However, I read about some other articles, which said that Java use static binding when dealing with overloading. It seems contradictory because obviously statement 1 is overloading.

I do not fully understand why Java called ovrLd() of base class in statement 2. If it used dynamic binding, it should call overLd() of sub class because by the runtime JVM should be clear that sub2 is an instance of BindingTest_Sub class. On the other hand, if it used static binding, it should also call overLd() of sub class because compiler is able to observe that the type of given argument is an Integer. Can you tell me what job has been done by compiler or JVM when it deals with statement 2.

The outcome of statement 3 makes sense to me. But still, I am curious about how the compiler recognize it (ovrRd()) as a overriding method. In another words, how does compiler know that there is another class which has a method that overrides this ovrRd().

Any thoughts about above questions or Java method binding mechanism is appreciated. Also please feel free to point out my mistakes.

解决方案

TL;DR; You're not really overloading ovrLd(Object), not in runtime. The compiler uses compile time type information to decide which is the best virtual method to call. sub1 and sub2 have different compile time types. And sub1's type has a different best match for ovrLb(Integer).

Explaining. You're wondering:

if sub1.ovrLd(new Integer(1)) calls BindingTest_Sub.ovrLd(Integer)

then why is sub2.ovrLd(new Integer(2)) is calling BindingTest_Base.ovrLd(Object)

In this case it works like this:

The compiler uses the compile time type information of the variable to decide which method to call.

The compile time type of sub2 is BindingTest_Base, in runtime you are assigning a BindingTest_Sub to it, but that's not relevant to the compiler.

The only method from BindingTest_Base that matches the parameters of that call is: BindingTest_Base.ovrLd(Object)

So the compiler issues a virtual call to orvLd(Object)

Now, the runtime method for a virtual call is decided based on the full signature of the method being invoked (name + parameters). And there is no overload for ovrLd(Object) in BindingTest_Sub

So the base class method is invoked.

With sub1 the compiler has more information. sub1's compile time type is BintdingTest_Sub and there is a method that matches ovrLd(Integer) in that class.

Looking at the bytecode you can see this clearly:

aload 1 // sub1

// ... blah blah blah creating the integer

// the last opcode issued by the compiler for "statement 1"

INVOKEVIRTUAL com/ea/orbit/actors/samples/helloworld/BindingTest_Sub.ovrLd (Ljava/lang/Integer;)V

aload 2 // sub2

// ... blah blah blah creating the integer

// the last opcode issued by the compiler for "statement 2"

INVOKEVIRTUAL com/ea/orbit/actors/samples/helloworld/BindingTest_Base.ovrLd (Ljava/lang/Object;)V

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值