知识大全 Java中引用,造型等问题解析
Posted 知
篇首语:既然认准一条路,就别去打听要走多久。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java中引用,造型等问题解析相关的知识,希望对你有一定的参考价值。
Java中引用,造型等问题解析 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
作者 chris译 或许大家java的多态问题 对上溯 下溯造型有了一定的概念 对protected和private大家想必也很清楚 但是 这几个个结合在一起 往往令人产生很多困惑 在这里 我举一个例子 大家或许会发觉这篇文章对你来说还是很有意义的:例子一共有两个class 可能出现困惑的地方我都会在后面一一解释 A是父类 B继承A 并且实现了protectedTest(Object obj)方法 如下面所示:
B java的源代码:
package matrix test; import matrix test A; /** * <p>Title: protect private and upcasting </p> * <p>Description: email:</p> * <p>Copyright: Matrix Copyright (c) </p> * <p>Company: </p> * @author chris * @version who use this example pls remain the declare */ public class B extends A protected int protectedb = ; protected int protectedab = ;
protected void protectedTest(Object obj) System out println("in B protectedTest(Object):" + obj);
A java的源代码:
package matrix test; import matrix test B; /** * <p>Title: protect private and upcasting </p> * <p>Description: email:</p> * <p>Copyright: Matrix Copyright (c) </p> * <p>Company: </p> * @author chris * @version who use this example pls remain the declare */
public class A protected int protecteda = ; protected int protectedab = ; private void privateTest() System out println("in A privateTest()"); protected void protectedTest(Object obj) System out println("in A protectedTest(Object):" + obj ); protected void protectedTest( String str ) System out println("in A protectedTest(String):" + str); public static void main (String[] args) // Test A A a = new A(); a privateTest(); // Test B String helloStr = "Hello"; Object helloObj = helloStr; B b = new B(); A a = b ; // 这里发生了什么?困惑 b =a ; //编译错误 困惑 b privateTest(); //编译错误 困惑 b protectedTest(helloObj); //输出结果?困惑 b protectedTest(helloStr); //编译错误 困惑 a protectedTest(helloObj); //输出结果? 困惑 a protectedTest(helloStr); //输出结果?困惑 ?
下面 我来逐个解释每一处困惑的地方:
困惑
这里其实就是子类自动上溯造型到父类A 这里a 其实是指向了一个B类型的对象 我们通常都可以这样作: A a =b 这样作的意思实际上就是让a 指向了一个类型B的对象—在这里就是b 了
在java里面 关于跨类引用 有两条规则应该记住:
如果a是类A的一个引用 那么 a可以指向类A的一个实例 或者说指向类A的一个子类
如果a是接口A的一个引用 那么 a必须指向实现了接口A的一个类的实例
所以 根据这两个规则 我们就不难理解例子中的A a = b 是什么意思了
困惑 :
A a = b 是可以的 但是为什么b =a 却是不行? 在这里 我们依然可以套用上面的两条规则 我们可以看到 b 是类B的一个引用 a 既不是类B的实例 也不是类B的子类的实例 所以直接b =a 就出现了编译错误
如果确实需要进行这样的转化 我们可以这样作:b =(B)a ; 进行强制转化 也就是下溯造型 在java里面 上溯造型是自动进行的 但是下溯造型却不是 需要我们自己定义强制进行
困惑 :
b privateTest();编译不通过? 这是很显然的 你可以回顾一下private的定义: 私有域和方法只能被定义该域或方法的类访问 所以 在这里 b 不能访问A的方法privateTest() 即使b 是A的子类的实例 请看下面的例子
public class A private int o(int i) return i; class Test extends A public static void main(String[] args) System out println(A o( ));
System out println(A o( ));这行编译出错 显然 因为private方法不能在这个类之外被访问 而protected则不同 我们回顾一下protected的定义: 被保护的域或方法只能被类本身 类的子类和同一程序包中的类所访问
下面是一个错误使用protected的例子:
package matrix test; public class ProtectedTest protected void show() System out println("I am in protected method");
import matrix test *; public class Test public static void main (String[] args) ProtectedTest obj = new ProtectedTest(); obj show();
因为访问权限问题 你会得到 show() has protected access in test ProtectedTest 的出错信息
困惑 :
b protectedTest(helloObj); 输出的是 in B protectedTest(Object):… 这到底是为什么呢? 为什么jvm能够确定是输出B的方法而不是A的方法? 这就和jvm的运行机制有关系了 我们上面提到了 a 是一个A类型的引用 但是指向了一个B类型的实例 在这里 如果jvm根据引用的类型 在这里就是A 来定义调用哪个方法的话 那么应该是调用A的protectedTest(helloObj)
然后实际上不是这样的 因为jvm的动态编译能力 jvm会在run time来决定调用哪一个method 而不是在pile time 也就是所谓的late binding(run time)和early binding(pile time)
困惑 :
b 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
在这里 我们遇到的是显式的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( );
你就会遇到编译错误 因为没有确定的指出 的类型 所以造成reference ambiguous的错误了
困惑
a protectedTest(helloObj);
相关参考
如果您认为Java游戏开发人员是Java编程世界的一级方程式赛车手那么您就会明白为什么他们会如此地重视程序的性能游戏开发人员几乎每天都要面对的性能问题往往超过了一般程序员考虑问题的范围哪里可以找到
Java的造型运算符 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 造型(Cast)的作用是与一
Java比c++方便的一点就是java有自己的垃圾收集机制可以自动帮你收集垃圾但是这并非意味着使用java我们就不需要考虑内存管理了 这一点相信很多java程序员都是知道的就是当一个对象我们决定
Java多语言编码问题解析(1) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! Java编译器在
Java多语言编码问题解析(2) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 这里是一个具体的
在公文拟稿中,如要引用某份公文应当_____。A、引用公文标题B、引用发文字号C、先引标题,后引发文字号D、先引发文字号,后引标题答案:C解析:在公文拟稿中,如要引用某份公文应当先引标题,后引发文字号
JavaSwing多线程死锁问题解析 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 在基于Jav
我国现有文献中最早引用勾股定理的是_____。A、《孙子算经》B、《周髀算经》C、《九章算术》D、《庄子算经》答案:B解析:我国现有文献中最早引用勾股定理的是《周髀算经》。《周髀算经》在数学上的主要成
一个类Callable不自己去调用自己的方法让其他类调用她(Callable)自身的方法(通过给其他类提供她自己的引用) 代码(一般javaGUI开发中添加按钮的点击事件)[java]viewp
在网页中的引用(比如引用cssjsimg等对象)总的来说可以分为以下几种方式 viewsourceprint?<%第一种方法%> <linkrel=stylesheettyp