在任何编程语言中,赋值操作都是最常见的操作之一,Java 自然也不例外。赋值时,使用赋值操作符=,它的意思是:“将等号右边的值(右值),复制给左边的值(左值)”。右值可以是任何常数、变量或者表达式(只要它能生成一个值就行)。但左值必须是一个明确的、已命名的变量。也就是说,必须有一个物理空间可以存储等号右边的值。例如:

int a = 4;

就是将一个常数赋给一个变量。但是不能把任何东西赋给一个常数。

  对于基本数据类型来说,赋值是很简单的,因为基本数据类型(在堆栈中)存储了实际的数值,而并非指向一个对象的引用,所有在为其赋值的时候,是直接将一个地方的内容复制到了另一个地方。但是在为对象“赋值”的时候,情况却发生了变化。对一个对象进行操作的时候,我们真正操作的是对象的引用,所以倘若“将一个对象赋值给另一个对象”,实际上是将“引用”从一个地方复制到另一个地方。这意味着如果对象在赋值的时候用b = c,那么对象bc都指向原本只有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);
}
}

如上面所示,我们建立了两个书籍对象thinkingInJavaheadFirstPattern,并分别对其价格进行赋值;然后,将对象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之后,别名现象即可消除。


温馨提示:此内容源于《Java编程思想》,可以通过阅读《Java编程思想》了解更多的内容。

原博地址:https://blog.csdn.net/qq_35246620/article/details/77601547

转自CSDN-详述 Java 中的别名现象的更多相关文章

  1. 死锁线程探讨Java中的死锁现象

    题记:写这篇博客要主是加深自己对死锁线程的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 今天搞了一下Java的死锁机制,感到自己还是不怎么懂,所以就从一些简略的源代码中琢磨:我先 ...

  2. java中的死锁现象

    死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. java 死锁产生的四个必要条件: 1.互斥使用,即当资源被一个线 ...

  3. java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了!      社区福利快来领取免费参加MDCC大会机会哦    Tag功能介绍—我们 ...

  4. Java方法调用中的别名处理

    将一个对象传递到方法内部时,也会产生别名现象.//: PassObject.java// Passing objects to methods can be a bit tricky62class L ...

  5. Java中各类Cache机制实现解决方案[来自CSDN]

    摘要:在Java中,不同的类都有自己单独的Cache机制,实现的方法也可能有所不同,文章列举了Java中常见的各类Cache机制的实现方法,同时进行了综合的比较. 在Java中,不同的类都有自己单独的 ...

  6. 【Java学习笔记之十五】Java中的static关键字解析

    Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...

  7. java中引用对比C++指针

    前置知识地址:https://blog.csdn.net/wangfei8348/article/details/51383805 重点在后面的引用对比实验(测试出内存地址,我很开心哈哈哈,客观给个好 ...

  8. 什么是uuid以及uuid在java中的使用

    什么是UUID?UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符.UUID具有以下涵义: 经由一定的算法机 ...

  9. Java中堆内存和栈内存有什么区别

    本文链接:https://blog.csdn.net/wangbo1998/article/details/80379016Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基 ...

随机推荐

  1. 在vue中调用echarts中的地图散点图~

    首先!当然是在vue中引入echarts! 命令行  npm install echarts --save 在main.js文件中里引入        import echarts from 'ech ...

  2. TFLite基础知识

    此基础知识仅为个人学习记录,如有错误或遗漏之处,还请各位同行给个提示. 概述 TFLite主要含有如下内容: (1)TFLite提供一系列针对移动平台的核心算子,包括量化和浮点运算.另外,TFLite ...

  3. 控制dom 加载成功后事件

  4. day1扩展作业

    作业一:博客作业二:编写登陆接口,●输入用户名密码(有文件存储用户名,命名)●认证成功后显示欢迎信息●输错三次后锁定(再次运行程序,还是输入上次输入的就显示已被锁定)作业三:多级菜单●三级菜单 ●可依 ...

  5. 找几张图片制作GIF

    1.打开Python,输入代码 import PIL.Image as Image #套用PIL函数 def get_gif(pics_dir,n,t): imgs = [] for i in ran ...

  6. Linux虚机安装配置Tomcat

    d第一步:下载Tomcat包,网址http://tomcat.apache.org/ 选择tar.gz包下载,并传到虚机中 第二步:解压下载好的Tomcat包 命令:tar -zxvf apache- ...

  7. 错误:Could not find a getter for CreatTime in class

    org.hibernate.PropertyNotFoundException: Could not find a getter for CreatTime in class org.com.xk.h ...

  8. spring MVC 入门:

    概述: MVC: M model 模型,除控制和视图以外,都可以成为模型. V view 视图,JSP,HTML,ASP,PHP,XHTML,FREEMARK,JSF,直接与用户做交互的资源. C c ...

  9. How to find out which version of tensorflow is installed in my pc? - 如何找出我的电脑中安装了哪个版本的 tensorflow?

    I'm using tensorflow and have got some weired issues. I'm told it might be related to the version of ...

  10. 历史命令与实时记录(redhat6.8)

    历史命令与实时记录(redhat6.8) linuxshell 2018年02月13日 10时58分53秒 参数 HISTTIMEFORMAT HISTSIZE HISTFILESIZE HISTFI ...