在任何编程语言中,赋值操作都是最常见的操作之一,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. [GXOI/GZOI2019]旧词

    很像LNOI 2014 LCA那道题. 同样的套路,离线以后直接扫描线. k=1的话就是原题. 考虑一般情况. 原本的做法是对x到根的这条链做一下区间+1操作,目的是为了是的在深度为i的位置得到的贡献 ...

  2. node-sass模块的安装

    使用淘宝源 npm config set sass_binary_site=https://npm.taobao.org/mirrors/node-sass/ npm config set phant ...

  3. hive的排序,分組练习

    hive的排序,分組练习 数据: 添加表和插入数据(数据在Linux本地中) create table if not exists tab1( IP string, SOURCE string, TY ...

  4. angular2学习笔记3

    一.项目搭建 二.生成首页的4个tab页面 三.运行部署及配置

  5. spiflash

    1.SPI Flash (即SPI Nor Flash)是Nor Flash的一种:2.NOR Flash根据数据传输的位数可以分为并行(Parallel)NOR Flash和串行(SPI)NOR F ...

  6. 框架-thrift-zookeeper-kafka

    Apache Thrift 是 Facebook 实现的一种高效的.支持多种编程语言的远程服务调用的框架. 目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 ...

  7. python小总结2(time,os)

    一.时间模块 1.1 Time time.time():获取时间戳,结果为一个浮点数 time.gtime():获取时间的元组形式 time.localtime():获取的是当地时间 time.mkt ...

  8. 【推荐】Data Structure Visualizations

    University of San Francisco    David Galles 功能:可视化数据结构&算法实现过程 网站地址  https://www.cs.usfca.edu/~ga ...

  9. SpringBoot配置Swagger实例(POST接收json参数)

    工程目录结构: 首先,引入jar包,只需要以下两个即可 <dependency> <groupId>io.springfox</groupId> <artif ...

  10. python dict to dataframe

    http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.from_dict.html Examples By de ...