详述 Java 中的别名现象

发表于:2017-8-28 13:11

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:维C果糖    来源:51Testing软件测试网采编

  在任何编程语言中,赋值操作都是最常见的操作之一,Java 自然也不例外。赋值时,使用赋值操作符=,它的意思是:“将等号右边的值(右值),复制给左边的值(左值)”。右值可以是任何常数、变量或者表达式(只要它能生成一个值就行)。但左值必须是一个明确的、已命名的变量。也就是说,必须有一个物理空间可以存储等号右边的值。例如:
  a = 4;
  就是将一个常数赋给一个变量。但是不能把任何东西赋给一个常数。
    对于基本数据类型来说,赋值是很简单的,因为基本数据类型(在堆栈中)存储了实际的数值,而并非指向一个对象的引用,所有在为其赋值的时候,是直接将一个地方的内容复制到了另一个地方。但是在为对象“赋值”的时候,情况却发生了变化。对一个对象进行操作的时候,我们真正操作的是对象的引用,所以倘若“将一个对象赋值给另一个对象”,实际上是将“引用”从一个地方复制到另一个地方。这意味着如果对象在赋值的时候用b = c,那么对象b和c都指向原本只有c指向的那个对象。通过下面的代码示例,我们将看到这个现象:
  package com.hit.operator;
  /**
   * @Author Charies Gavin
   * @Date 2017/8/26,下午1:38
   * @GitHub https://github.com/guobinhit
   */
  public class Book {
      int price;
  }
  如上面的代码所示,我们建立了一个Book类,用来表示书籍,其仅有一个字段price,表示书籍的价格。
  package com.hit.operator;
  /**
   * @Author Charies Gavin
   * @Date 2017/8/26,下午1:38
   * @GitHub https://github.com/guobinhit
   */
  public class Assignment {
      public static void main(String[] args) {
          // 创建两个实体对象
          Book thinkingInJava = new Book();
          Book headFirstPattern = new Book();
          // 分别赋值
          thinkingInJava.price = 108;
          headFirstPattern.price = 68;
          System.out.println("Thinking In Java : price is " + thinkingInJava.price);
          System.out.println("Head First Pattern : price is " + headFirstPattern.price);
          // 将 headFirstPattern (的引用)赋值给 thinkingInJava
          thinkingInJava = headFirstPattern;
          System.out.println("Thinking In Java : price is " + thinkingInJava.price);
          System.out.println("Head First Pattern : price is " + headFirstPattern.price);
          // 修改 thinkingInJava 的价格(值),半价出售
          thinkingInJava.price = 54;
          System.out.println("Thinking In Java : price is " + thinkingInJava.price);
          System.out.println("Head First Pattern : price is " + headFirstPattern.price);
      }
  }
  如上面所示,我们建立了两个书籍对象thinkingInJava和headFirstPattern,并分别对其价格进行赋值;然后,将对象headFirstPattern的引用赋值给thinkingInJava;接下来,调用thinkingInJava.price,修改其价格为半价。最后,运行程序,输出结果。显然,由于对象的赋值是操作的对象引用,因此在我们改变thinkingInJava的价格时,headFirstPattern的价格也随之改变。这种现象,我们称之为“别名现象”。
    当然,我们有时候并不希望发生别名现象,但如何避免呢?其实,想要避免别名现象也很简单,以上面的代码为例,我们只需要将对象赋值时的语句略作修改即可,如下所示:
  package com.hit.operator;
  /**
   * @Author Charies Gavin
   * @Date 2017/8/26,下午1:38
   * @GitHub https://github.com/guobinhit
   */
  public class Assignment2 {
      public static void main(String[] args) {
          // 创建两个实体对象
          Book thinkingInJava = new Book();
          Book headFirstPattern = new Book();
          // 分别赋值
          thinkingInJava.price = 108;
          headFirstPattern.price = 68;
          System.out.println("Thinking In Java : price is " + thinkingInJava.price);
          System.out.println("Head First Pattern : price is " + headFirstPattern.price);
          // 将 headFirstPattern (的属性值)赋值给 thinkingInJava
          thinkingInJava.price = headFirstPattern.price;
          System.out.println("Thinking In Java : price is " + thinkingInJava.price);
          System.out.println("Head First Pattern : price is " + headFirstPattern.price);
          // 修改 thinkingInJava 的价格(值),半价出售
          thinkingInJava.price = 54;
          System.out.println("Thinking In Java : price is " + thinkingInJava.price);
          System.out.println("Head First Pattern : price is " + headFirstPattern.price);
      }
  }


  如上面所示,当我们将thinkingInJava = headFirstPattern修改为thinkingInJava.price = headFirstPattern.price之后,别名现象即可消除。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号