网站首页
JSP空间
动态资讯
开源项目
技术文档
资源下载
J2EE资源
客户论坛
在线支付
 
  技术文档>>JAVA>>新手入门>>基础入门>查看文档  
  java中引用,造型等问题解析     
  文章作者:未知  文章来源:水木森林  
  查看:71次  录入:管理员--2007-11-17  
 
  作者:chris译
  
   或许大家java的多态问题,对上溯,下溯造型有了一定的概念,对protected和private大家想必也很清楚,但是,这几个个结合在一起,往往令人产生很多困惑,在这里,我举一个例子,大家或许会发觉这篇文章对你来说还是很有意义的:
  

  例子一共有两个class. 可能出现困惑的地方我都会在后面一一解释.a是父类,b继承a,并且实现了protectedtest(object obj)方法.如下面所示:
  


  

b.java的源代码:


  

package cn.org.matrix.test;

   import cn.org.matrix.test.a;

   /**

   * <p>title: protect, private and upcasting </p>

   * <p>description: email:chris@matrix.org.cn</p>

   * <p>copyright: matrix copyright (c) 2003</p>

   * <p>company: matrix.org.cn</p>

   * @author chris

   * @version 1.0,who use this example pls remain the declare

   */

   public class b extends a

   {

   protected int protectedb = 0;

   protected int protectedab = 0;

  


  

protected void protectedtest(object obj)

   {

   system.out.println("in b.protectedtest(object):" + obj);

   }

   }

  


  



   a.java的源代码:


  

package cn.org.matrix.test;

   import cn.org.matrix.test.b;

   /**

   * <p>title: protect, private and upcasting </p>

   * <p>description: email:chris@matrix.org.cn</p>

   * <p>copyright: matrix copyright (c) 2003</p>

   * <p>company: matrix.org.cn</p>

   * @author chris

   * @version 1.0,who use this example pls remain the declare

   */


  

public class a

   {

   protected int protecteda = 0;

   protected int protectedab = 0;

   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 a1 = new a();

   a1.privatetest();

   // test b

   string hellostr = "hello";

   object helloobj = hellostr;

   b b1 = new b();

   a a2 = b1; // 这里发生了什么?困惑1

   b1=a1; //编译错误,困惑2

   b1. privatetest(); //编译错误,困惑3

   b1.protectedtest(helloobj); //输出结果?困惑4

   b1.protectedtest(hellostr); //编译错误,困惑5

   a2.protectedtest(helloobj); //输出结果? 困惑6

   a2.protectedtest(hellostr); //输出结果?困惑7 ?

   }

   }

  


  



   下面,我来逐个解释每一处困惑的地方:


  

困惑1:


  

  这里其实就是子类自动上溯造型到父类a。这里a2其实是指向了一个b类型的对象. 我们通常都可以这样作: a a2=b1, 这样作的意思实际上就是让a2指向了一个类型b的对象—在这里就是b1了.
  


  

在java里面,关于跨类引用,有两条规则应该记住:


  

1. 如果a是类a的一个引用,那么,a可以指向类a的一个实例,或者说指向类a的一个子类.


  

2. 如果a是接口a的一个引用,那么,a必须指向实现了接口a的一个类的实例.


  

  所以,根据这两个规则,我们就不难理解例子中的a a2 = b1是什么意思了.


  

困惑2:


  

  a a2 = b1是可以的,但是为什么b1=a1却是不行? 在这里,我们依然可以套用上面的两条规则,我们可以看到,b1是类b的一个引用,a1既不是类b的实例,也不是类b的子类的实例,所以直接b1=a1就出现了编译错误.
  


  

  如果确实需要进行这样的转化,我们可以这样作:b1=(b)a1; 进行强制转化,也就是下溯造型. 在java里面,上溯造型是自动进行的,但是下溯造型却不是,需要我们自己定义强制进行.
  


  

困惑3:


  

b1. privatetest();编译不通过? 这是很显然的,你可以回顾一下private的定义: 私有域和方法只能被定义该域或方法的类访问.所以,在这里,b1不能访问a的方法privatetest(),即使b1是a的子类的实例.请看下面的例子:
  


  

public class a

   {

   private int two(int i) { return i; }

   }

   class test extends a {

   public static void main(string[] args) {

   system.out.println(a.two(3));

   }

   }

  


  



     system.out.println(a.two(3));这行编译出错,显然,因为private方法不能在这个类之外被访问.而protected则不同,我们回顾一下protected的定义:
   被保护的域或方法只能被类本身、类的子类和同一程序包中的类所访问.


  

  下面是一个错误使用protected的例子:


  

package cn.org.matrix.test;

   public class protectedtest {

   protected void show() {

   system.out.println("i am in protected method");

   }

   }


  

import cn.org.matrix.test.*;

   public class test {

   public static void main (string[] args) {

   protectedtest obj = new protectedtest();

   obj.show();

   }

   }

  


  



     因为访问权限问题,你会得到”show() has protected access in test.protectedtest”的出错信息.


  

困惑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的错误了.


  

困惑6:


  

a2.protectedtest(helloobj);

  


  



   输出结果分别是:”in b.p

 
 
上一篇: java抽取word,pdf的四种武器    下一篇: 好的连接池,免费的
  相关文档
遍历m取n的所有组合 03-25
bea的workshopstudio开发者的ide利器 11-17
java基础:swing中的事件处理详细资料 11-16
j2ee设计模式浅谈(1) 11-17
simply singleton -- part1 by david geary 11-17
java语言能扮演嵌入式应用开发的主角吗? 11-16
新手上路:初学java注意什么 11-16
web服务让cio们左右为难 选择.net还是java 11-17
对《java与模式》中工厂方法模式的异议 11-17
j2me中使用缓存将屏幕内容存储为image 11-17
用ajax+j2ee实现网上会议室系统 11-17
深入spring mvc framework之总体分析 11-17
使用midp2.0开发游戏(4)改进的地图生成方式 11-17
struts模块化编程教程(三) 11-17
java learning path (一)、工具篇 11-17
谈谈j2se中的序列化之接受默认序列化 11-16
jbuilder2006破解补丁 11-17
java基础之api零碎总结 03-25
软件操作界面设计须遵循的一些原则 11-17
java高手帮你解析xml配置文件的读取操作 09-10
返回首页 | 关于我们 | J网章程 | JSP空间合租 | 客服中心 | 免责声明 | 常见问题 | 参观机房
本站主机空间代理至厦门市华众网络科技有限公司
《中华人民共和国增值电信业务经营许可证》
编号:闽B2-20050079
@2005-2008福建JSP技术网 版权所有 闽ICP备05000928号
技术电话:13616026886
邮箱:admin@fjjsp.com 站长QQ,点击这里给我发消息