翻译人员: 铁锚

翻译时间: 2013年11月13日

原文链接: How does Java handle aliasing?

什么是Java的引用别名机制

Java的引用别名机制(原文为Aliasing,别名,即Java中的多态)意味着多个引用变量可以定位到同一个实际物理对象,而这些引用变量可以是不同的类型.

下面的代码中,S类继承P类, pp 和 ss 分别是P类型 和 S类型的两个数组变量名.

public class TestPolyMorphism {
    public static class P{
    public void print(String message){
        System.out.println("P-->"+message);
    }
    }
    public static class S extends P{
    public void print(String message){
        System.out.println("S-->"+message);
    }
    }
    public static void main(String[] args) {
    S[] ss = new S[10];
    P[] pp = ss;
    ss[0] = new S();
    pp[0].print("你好");
    // !!运行时错误,不能将父类对象,赋给子类数组;
    //pp[1] = new P();//java.lang.ArrayStoreException
    }
}

在内存中,pp和ss都指向了同样的内存地址.(我们可以说,指针pp,指针ss;或者说pp引用,ss引用.)

图1

pp和ss指向了同一个物理地址,在实际运行过程中,多态特性根据真实的对象类型决定调用父类还是子类的具体方法,而不是根据引用变量的类型.



Java 如何处理引用别名机制

如果将下列代码拷贝到eclipse中,将不会有什么编译期错误:

package think;

public class TestPolyMorphism {
    public static class P{
    public void print(String message){
        System.out.println("P-->"+message);
    }
    }
    public static class S extends P{
    public void print(String message){
        System.out.println("S-->"+message);
    }
    public void paint(String message){
        System.out.println("S-->执行一些绘画操作-->"+message);
    }
    }
    public static void main(String[] args) {
    S[] arr = new S[10];
    P[] pp = arr;
    arr[0] = new S();
    pp[0].print("你好");
    pp[1] = new P(); // !!运行时错误,不能将父类对象,赋给子类数组;java.lang.ArrayStoreException
    }
}

但在运行期将会显示如下错误:

Exception in thread "main" java.lang.ArrayStoreException: think.TestPolyMorphism$P
    at think.TestPolyMorphism.main(TestPolyMorphism.java:22)

原因是Java在运行时才处理别名引用,在程序运行过程中,虚拟机发现 数组pp的第一个元素是 SS类型的对象,而不是PP类型的。

因此,只有修改为正确的代码,才可以正常运行:

S[] arr = new S[10];
P[] pp = arr;
pp[1] = new S();
pp[1].print("你好");

输出没有错误:

S-->你好

相关文章:

1. Linux Process Programming – fork()

2. 图说Java —— 理解Java机制最受欢迎的8幅图

3. Why do we need Generic Types in Java?

4. Overriding and overloading in Java with examples

Java对象引用处理机制的更多相关文章

  1. 「轉」Java的内存机制

    0.参考资料: http://www.j2megame.org/index.php/content/view/2246/125.html 1.Java的内存机制 Java 把内存划分成两种:一种是栈内 ...

  2. Java GC回收机制

    优秀Java程序员必须了解的GC工作原理 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,因为有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只 ...

  3. 成为JavaGC专家(1)—深入浅出Java垃圾回收机制

    转载自:http://www.importnew.com/1993.html 对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC ...

  4. Java内存回收机制

    在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险.但是,也正 ...

  5. Java中反射机制和Class.forName、实例对象.class(属性)、实例对象getClass()的区别

    一.Java的反射机制   每个Java程序执行前都必须经过编译.加载.连接.和初始化这几个阶段,后三个阶段如下图:   其中

  6. Java 动态代理机制分析及扩展

    Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...

  7. [转]Java 动态代理机制分析及扩展

    引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...

  8. java 垃圾回收机制 引用类型

    Java语言的一个重要特性是引入了自动的内存管理机制,使得开发人员不用自己来管理应用中的内存.C/C++开发人员需要通过malloc/free 和new/delete等函数来显式的分配和释放内存.这对 ...

  9. 转:成为JavaGC专家Part I — 深入浅出Java垃圾回收机制

    文章来自于:http://www.importnew.com/1993.html 对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解 ...

随机推荐

  1. Sprk SQL

    一.Spark SQL概述  1.Spark SQL的前生今世 Shark是一个为Spark设计的大规模数据仓库系统,它与Hive兼容.Shark建立在Hive的代码基础上,并通过将Hive的部分物理 ...

  2. linux 防火墙操作

    root/12345 (只能用ROOT操作)iptables -I INPUT -s x.x.x.x -p tcp --dport 8091 -j ACCEPT   #允许x.x.x.x访问本机的80 ...

  3. [CSDN_Markdown]使用LaTeX基本数学公式

    简介 以前我很头疼在博文里写公式,一直期盼CSDN的博文编辑器能支持LaTeX 公式输入,今天终于可以使用这个功能了!此文主要讨论如何在CSDN的Markdown编辑器中写 LaTeX 公式! 使用L ...

  4. BI Publisher(rtf)模板开发语法大全

    Rtf模板开发例如背景,纹理分栏等等功能都能用word工具实现不再具体总结大家可以参考word教程.....   一.组 定义一个组的目的是告诉XMLPublisher对重复的数据行进行循环显示,也就 ...

  5. Linux命令—压缩及其他

     (1)为了更好的传送和保存文件,需要对某些文件和目录进行压缩和解压缩操作,Linux 提供了强大的压缩.解压缩命令,常用的tar命令. (2)在Linux中,如果要使用储存设备(硬盘.光驱.移动 ...

  6. Android View框架总结(四)View布局流程之Measure

    View树的measure流程 View的measures时序图 View布局流程之measure measure过程 View的measure过程 ViewGroup的measure过程 Frame ...

  7. linux C++多线程操作文件&输出加锁

    下述demo将指定目录下文件存入vector,然后一分为二交给两个线程(threadTask1,threadTask2)去分别处理,对输出函数printDirent加锁防止紊乱. #include & ...

  8. <<精通iOS开发>>第14章例子代码小缺陷的修复

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 首先推荐大家看这本书,整本书逻辑非常清晰,代码如何从无到有,到 ...

  9. Servlet编程实例-servlet学习之旅(三)

    LoginServlet代码: public class LoginServlet extends HttpServlet{ @Override protected void service(Http ...

  10. 没想到你是这样的UDP

    UDP是国际标准化组织为互联网设定的标准中的传输层中的一个协议.TCP/IP协议簇是一个很庞大的家族,但是今天我们就来看一看这个面向无连接的传输层在Java中是怎样通过编程实现的. 原理性知识 在Ja ...