知识大全 引用 造型 protected和private的困惑
Posted 知
篇首语:有学问和有知识的人是不同的。记忆造成了前者,哲学造成了后者。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 引用 造型 protected和private的困惑相关的知识,希望对你有一定的参考价值。
或许大家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); 输出结果分别是 in B protectedTest(Object) 经过上面的解释 想必大家都能很清楚的知道为什么会有这两个输出结果了 a protectedTest(helloObj);因为jvm的late binding 所以在run time的时候 调用了B类的方法 虽然在编译期间a 只是一个父类A的引用类型 困惑 a protectedTest(helloStr); 为什么这里会输出 in A protectedTest(Object)… 为什么这里不会编译出错?为什么b protectedTest(helloStr)会出错而a protectedTest(helloStr)会出错?我调用了a equals(b )和a ==b 得到的结果都是true啊?但是为什么这里出这个错误? 在这里 这个问题是最关键的 也是我们放到最后来解答的原因 首先 回顾一下equals()和==的在java里面的概念 记得有一道scjp cha138/Article/program/Java/JSP/201311/19162相关参考
知识大全 c#中private私有和public公有的区别是什么
c#中private私有和public公有的区别是什么private、protect、public、访问范围依次增大。private只限在本类中使用。protect允许它的子类访问。public修饰符
现在我们已理解了继承的概念protected这个关键字最后终于有了意义在理想情况下private成员随时都是私有的任何人不得访问但在实际应用中经常想把某些东西深深地藏起来但同时允许访问衍生类的成员
Java中引用,造型等问题解析 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 作者chris译
C#中private在方法中怎么用?和public有什么区别?请高手帮忙解答! 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,
知识大全 ORACLE Virtual Private Database 全新体验
ORACLEVirtualPrivateDatabase全新体验 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起
工作已经有一年有余做项目的时侯经常碰到值类型和引用类型当时对这两个概念很难理解今闲暇之时翻看红皮书顿有所悟和大家分享一下 从概念上区分值类型直接存储其值引用类型存储对值的饮用按照存储位置上的不同
在C#中既可以通过值也可以通过引用传递参数通过引用传递参数允许函数成员(方法属性索引器运算符和构造函数)更改参数的值并保持该更改若要通过引用传递参数请使用ref或out关键字为简单起见本主题的示例
注意C++和C#引用的区别 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! C#用多了最近又回到C
知识大全 在excel中,不是数据引用方式有A相对引用B交叉引用C绝对引用D混合引用
在excel中,不是数据引用方式有A相对引用B交叉引用C绝对引用D混合引用 以下文字资料是由(本站网www.cha138.com)小编为大家搜集整理后发布的内容,让我们
知识大全 公司百度百科参考资料可以引用公司官网么?网站是全flash的,每个引用处页面都是一个地址。
公司百度百科参考资料可以引用公司官网么?网站是全flash的,每个引用处页面都是一个地址。根据百度百科的规则百度百科的参考资料不能引用公司官网作为参考资料,除非公司官网具有权威性和公正性。百度百科为了