在任何编程语言中,赋值操作都是最常见的操作之一,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. Educational Codeforces Round 53 (Rated for Div. 2)G. Yet Another LCP Problem

    题意:给串s,每次询问k个数a,l个数b,问a和b作为后缀的lcp的综合 题解:和bzoj3879类似,反向sam日神仙...lcp就是fail树上的lca.把点抠出来建虚树,然后在上面dp即可.(感 ...

  2. JavaJ2EE相关知识整理

    1.Servlet的生命周期     在Web容器中,Servlet主要经历4个阶段      ①.加载Servlet:当Tomcat第一次访问Servlet的时候,Tomcat会负责创建Servle ...

  3. io.undertow.websockets.jsr.ServerWebSocketContainer cannot be cast to org.apache.tomcat.websocket.server.WsServerContainer

    Caused by: java.lang.ClassCastException: io.undertow.websockets.jsr.ServerWebSocketContainer cannot ...

  4. jquery 浮动 固定显示

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>无标题文档 我爱b ...

  5. Redhat 6.3上安装CMake

    在编译libssh时,要用到CMake,而且要依赖3.3以上的版本. 尝试了从CMake官网下载源码,编译安装.结果发现各种依赖,比如要升级GCC,升级Python等等,麻烦要死.搞了半天还是一堆问题 ...

  6. 通信技术以及5G和AI保障电网安全与网络安全

    摘 要:电网安全是电力的基础,随着智能电网的快速发展,越来越多的ICT信息通信技术被应用到电力网络.本文分析了历史上一些重大电网安全与网络安全事故,介绍了电网安全与网络安全.通信技术与电网安全的关系以 ...

  7. 集合框架之map

    Map实现类用于保存具有映射关系的数据.Map保存的每项数据都是key-value对,也就是由key和value两个值组成.Map里的key是不可重复的,key用户标识集合里的每项数据. Map提供了 ...

  8. Python_Mix*匿名函数,sorted,filter,map,递归函数,二分法查找

    lambda匿名函数(函数名统一都叫lambda) 为了解决简单的需求而设计的一句话函数 语法: lambda 参数 返回值 n = lambda a,b: max(a,b) ret = n(9,4) ...

  9. spring整合redis(哨兵模式)

    首先服务器搭建哨兵模式(我这里使用的是Windows8系统),感谢两位博主,少走不少弯路,在此给出链接:服务器哨兵模式搭建和整合哨兵模式 什么一些介绍就不介绍了,可以看一下连接,比较详细,初次接触,当 ...

  10. C语言:开平方根sqrt程序02

    #include <stdio.h> int sqrt01(int x); void main(void){ int x=49,y; y=sqrt01(x); if(y<0) pri ...