转自CSDN-详述 Java 中的别名现象
在任何编程语言中,赋值操作都是最常见的操作之一,Java 自然也不例外。赋值时,使用赋值操作符=,它的意思是:“将等号右边的值(右值),复制给左边的值(左值)”。右值可以是任何常数、变量或者表达式(只要它能生成一个值就行)。但左值必须是一个明确的、已命名的变量。也就是说,必须有一个物理空间可以存储等号右边的值。例如:
int 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之后,别名现象即可消除。
温馨提示:此内容源于《Java编程思想》,可以通过阅读《Java编程思想》了解更多的内容。
原博地址:https://blog.csdn.net/qq_35246620/article/details/77601547
转自CSDN-详述 Java 中的别名现象的更多相关文章
- 死锁线程探讨Java中的死锁现象
题记:写这篇博客要主是加深自己对死锁线程的认识和总结实现算法时的一些验经和训教,如果有错误请指出,万分感谢. 今天搞了一下Java的死锁机制,感到自己还是不怎么懂,所以就从一些简略的源代码中琢磨:我先 ...
- java中的死锁现象
死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. java 死锁产生的四个必要条件: 1.互斥使用,即当资源被一个线 ...
- java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET
java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了! 社区福利快来领取免费参加MDCC大会机会哦 Tag功能介绍—我们 ...
- Java方法调用中的别名处理
将一个对象传递到方法内部时,也会产生别名现象.//: PassObject.java// Passing objects to methods can be a bit tricky62class L ...
- Java中各类Cache机制实现解决方案[来自CSDN]
摘要:在Java中,不同的类都有自己单独的Cache机制,实现的方法也可能有所不同,文章列举了Java中常见的各类Cache机制的实现方法,同时进行了综合的比较. 在Java中,不同的类都有自己单独的 ...
- 【Java学习笔记之十五】Java中的static关键字解析
Java中的static关键字解析 static关键字是很多朋友在编写代码和阅读代码时碰到的比较难以理解的一个关键字,也是各大公司的面试官喜欢在面试时问到的知识点之一.下面就先讲述一下static关键 ...
- java中引用对比C++指针
前置知识地址:https://blog.csdn.net/wangfei8348/article/details/51383805 重点在后面的引用对比实验(测试出内存地址,我很开心哈哈哈,客观给个好 ...
- 什么是uuid以及uuid在java中的使用
什么是UUID?UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符.UUID具有以下涵义: 经由一定的算法机 ...
- Java中堆内存和栈内存有什么区别
本文链接:https://blog.csdn.net/wangbo1998/article/details/80379016Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基 ...
随机推荐
- js点击加载更多可以增加几条数据的显示
<div class="list"> <div class="one"> <div class="img" ...
- react和vue的不同
React严格上只针对MVC的view层,Vue则是MVVM模式 virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树.而对于React而言,每当应用的状态被改变时 ...
- 在jsp中如何使用javax.servlet.http.HttpServlet,javax.servlet.GenericServlet, javax.servlet.Servlet
- Python3+unittest使用教程
一.直接使用TestCase 注意所有测试方法都需要以test开头.代码如下: import unittest class Test1(unittest.TestCase): @classmethod ...
- mysql中用limit 进行分页有两种方式
代码示例:语句1: select * from student limit 9,4 语句2: slect * from student limit 4 offset 9 // 语句1和2均返回表stu ...
- CentOS 7系统上添加netcdf库
这里提供两种方法来安装 netcdf: 一是 yum 安装,yum 安装时采用的是系统自带的 gfortran 编译器,版本较旧: 二是采用源码来 Makefile 编译安装的方式,它可以下载最新版的 ...
- SQL语句实现行转列
最近在维护一个项目,出现了一下bug需要进行调试,于是把正式库上面的代码搬到本地库上面,数据库是本地的,跑项目的时候调试发现代码里面带有wmsys.wm_concat函数的SQL语句出现错误,经排查发 ...
- 前端必备之Node+mysql+ejs模版如何写接口
前端必备之Node+mysql+ejs模版如何写接口 这星期公司要做一个视频的后台管理系统, 让我用Node+mysql+ejs配合写接口, 周末在家研究了一下, 趁还没来具体需求把研究内容在这里分享 ...
- Linq 27个常用操作符说明
1.Where 操作符用于限定输入集合中的元素,将符合条件的元素组织声称一个序列结果.2.Select 操作符用于根据输入序列中的元素创建相应的输出序列中的元素,输出序列中的元素类型可以与输入序列中 ...
- idea的破解及相关安装
---- idea的破解 -javaagent:../bin/JetbrainsCrack-2.7-release-str.jar 复制到相关的idea配置文件 并将该Jar包复制到idea的bin目 ...