困惑4:
b1.protectedTest(helloObj); 输出的是"in B.protectedTest(Object):…" 这到底是为什么呢? 为什么jvm能够确定是输出B的方法而不是A的方法? 这就和jvm的运行机制有关系了. 我们上面提到了,a1是一个A类型的引用,但是指向了一个B类型的实例. 在这里,如果jvm根据引用的类型-在这里就是A 来定义调用哪个方法的话,那么应该是调用A的protectedTest(helloObj).
然后实际上不是这样的,因为jvm的动态编译能力,jvm会在run-time来决定调用哪一个method,而不是在compile time. 也就是所谓的late-binding(run-time)和early-binding(compile-time).
困惑5:
b1.protectedTest(helloStr); 这里为什么会出现编译错误? 他可以调用类B的protectedTest(Object obj)方法啊,把helloStr上溯造型成一个object就行了啊..或者上溯造型到A然后调用A的protectedTest(helloStr)方法。
问题的根源就在于此了,既然有两种选择,jvm应该选择那一种?这种不确定性如果交给jvm来动态决定的话,势必带来程序的不确定性..虽然java在其他的一些地方也有类似的情形出现,比如static变量的循环定义造成的不确定性,但是,在这里,jvm还是在编译阶段就解决了这个问题。
所以,我们会在这一步遇到编译错误: "reference to protectedTest is ambiguous; both method protectedTest(java.lang.String) in mytest.A and method protectedTest(java.lang.Object) in mytest.B match at line 46.
在这里,我们遇到的是显式的reference ambiguous错误,但是,有时候,隐式的reference ambiguous却往往是更加的危险。
在这里,我举个例子:
父类的 源代码:
public super { private void test(int i, long j); { System.out.println(i+"and"+j); } } 子类的源代码: public sub { private void test(long j, int i); { System.out.println(i+"and"+j); } }
子类和父类都用有相同名称的方法test,参数类型不同而已.这种情况下,编译可以被通过. 但是如果你在另外一个类中用到了如下代码:
Sub sb = new Sub(); sb.test(100, 3000);
你就会遇到编译错误,因为没有确定的指出3000的类型,所以造成reference ambiguous的错误了.
|
|