Java编程中值得注意的对象引用现象

        Java中的类根据赋值对象与被赋值对象是否共享对象的实际数据内存空间,分为值型类引用型类

        Java中将一个对象赋值给另一个对象时,如果这个对象是值对象(所谓的值对象就是由值型类生成的对象),则这两个对象的实际数据存储空间是独立的,各自保存数据的拷贝。因此分别修改这两个对象不会相互影响。如果这个对象是引用型对象(所谓的引用型对象就是由引用型类生成的对象),则这两个对象的实际数据存储空间是相同的,两者共享实际数据存储区。因此,分别修改这两个对象时,实质上同时修改了另一个对象的数据。此时,赋值前后看似有两个对象,实际上同一个对象的两个不同引用而已,两者所指向的对象数据区是相同的。

        Java中的值型类包括表示基本数据类型的类(例如Integer,Long,Double,Float,Boolean,Byte,String,Character等),除此之外的其他Java内置类以及所有的用户自定义类均属于引用型类

先看一个小实验:

        Integer b1=new Integer(123);  //新建一个Integer类的对象
        Integer b2=b1; //将对象b1赋值给b2
        b2=456; //修改b的值
        System.out.println(b1); //观察b1的值是否在被b2修改了。  以上处的运行结果是123,表明Integer类型是值类型。
        StuInfo s1,s2;     //观察自定义类型StuInfo,其定义见稍后代码。           
        s1=new StuInfo(18001,"张一"); //新建一个StuInfo类的对象
        s2=s1; //将对象s1赋值给s2
        s2.setId(123); //修改s2的值
        System.out.println(s1); //观察s1的值是否被s2修改了。  以上处的运行结果是“学号:123 姓名:张一”,表明Integer类是引用型类。
 

    明白了以上现象后,在实际编程中应该要特别注意。例如,在将对象添加到链表ArrayList后,此对象和链表中对应的元素其实都是指向相同的对象数据存储空间,也就是说此对象和链表中对应的元素是同一对象数据区的两个引用,通过任何其中一个引用修改对象数据区,实际上也修改了另一个引用的对象数据区,因为两个引用指向同一对象数据区。      

    下面的程序展示了这种现象。

import java.util.ArrayList;

public class MyTest {

    public static void main(String[] args) {
        StuInfo s1,s2,s3;        
        ArrayList<StuInfo> list=new ArrayList<StuInfo>();        
        
        s1=new StuInfo(18001,"张一"); //新建3个对象s1,s2,s3          
        s2=new StuInfo(18002,"王二");       
        s3=new StuInfo(18003,"赵三");
        list.add(s1); //将3个对象s1,s2,s3添加到链表list中
        list.add(s2);      
        list.add(s3);        
        for(StuInfo e:list)           //输出链表中的对象
            System.out.println(e);        
        System.out.println();
        
        s1.setId(11);                //修改对象s1,s2,s3的值
        s1.setName("张十一");        
        s2.setId(22);
        s2.setName("王二二");        
        s3.setId(33);
        s3.setName("赵三三");        
        for(StuInfo e:list)              //观察链表list中的对象值是否发生变化。结果是确实发生了改变。
            System.out.println(e);  //也就是修改s1,s2,s3的值实际上修改了链表中对应元素的值。
        System.out.println();
        
        for(StuInfo e:list)             //修改链表中对象的值
            e.setId(e.getId()+10);        
        System.out.println(s1);   //观察对象s1,s2,s3的值是否发生了改变。结果是确实发生了改变。
        System.out.println(s2);   //也就是修改链表中对应元素的值实际上修改了的对象s1,s2,s3的值。
        System.out.println(s3);    
    }
}
    

//以下为StuInfo类的定义
class StuInfo{  
    private int id;
    private String name;    
    
    public StuInfo(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "学号:"+id+"\t姓名:"+name;
    }
    
}

以上程序的运行结果:

学号:18001    姓名:张一
学号:18002    姓名:王二
学号:18003    姓名:赵三

学号:11    姓名:张十一
学号:22    姓名:王二二
学号:33    姓名:赵三三

学号:21    姓名:张十一
学号:32    姓名:王二二
学号:43    姓名:赵三三
 

    如果实际编程中需要避免这种两个对象引用同一对象数据区的情形发生,解决办法有2个。

    办法1:覆盖(override)该类的clone()方法(在该clone()方法中,先new一个新对象,然后将对象的所有数据成员分别一一赋值给新对象,最后返回新对象),那么在原来给对象赋值的操作,改为调用clone()方法。例如,将s2=s1语句改为s2=s1.clone(),即可。

    办法2:实现方法1中clone()函数的方式设计一个构造函数,该构造函数的参数是同类对象。这种构造函数有时称为“拷贝构造函数”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/262410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提高ASP.net性能的十种方法

一、返回多个数据集 检查你的访问数据库的代码&#xff0c;看是否存在着要返回多次的请求。每次往返降低了你的应用程序的每秒能够响应请求的次数。通过在单个数据库请求中返回多个结果集&#xff0c;可以减少与数据库通信的时间&#xff0c;使你的系统具有扩展性&#xff0c;…

java mysql failover_mysqlfailover测试

mysqlfailover是mysql官方用python语言写的一款工具&#xff0c;包含在mysql utilities工具集中。主要作用是保障mysql高可用。他会定时检测节点状态&#xff0c;当master节点不可用时&#xff0c;会自动转移到从节点上&#xff0c;同时剩余的从节点都会指向转以后的节点。如何…

RGB/YUV/YCbCr--关于显示,颜色你需要了解的一些事

工作中常听说RGB/YUV/YCbCr 这样一些名词&#xff0c;概念上似乎很混淆&#xff1f;这里是一个简介&#xff0c;部分内容来自wiki&#xff0c;理解不对的地方欢迎指正。 A&#xff1a;首先两个基本概念&#xff1a; Color model和Color Space. 1. Color Model: 为了表达人眼观察…

C# winfrom listView

转自http://hi.baidu.com/gaoisbest/item/84034943d4d94195823ae12b 1.如何为listview手动添加第一列和第二列数据 for (int i 0; i < 10; i) { ListViewItem Item new ListViewItem(); Item.Text dt.Rows[i][1].ToString();//读取数据库中字段 Item.Tag dt.…

淘宝评价网----类反淘宝联盟上线

反淘宝联盟&#xff0c;淘宝该反吗&#xff1f; 淘宝该反对吗&#xff1f; 其实淘宝已经做的很好了 我们反对的只是商家的不诚信的行为&#xff0c;但是在淘宝上我们又得不到对商家的全面的全面了解&#xff0c;所以我们反了&#xff1b;反&#xff0c;只是途径&#xff0c;不是…

Python从键盘输入多行文本数据的方法

Python中的Input()函数在输入时&#xff0c;遇到回车符&#xff0c;那么一次输入就结束了。这不能满足输入多行文本并且行数也不确定的情形&#xff0c;当然输入空行也是允许的。 方法1&#xff1a;直接利用input()函数逐行读取数据&#xff0c;直到EOF。利用异常处理机制实现…

[教程指导]索尼官方4.0.3系统一键root方法! [复制链接]

[教程指导]索尼官方4.0.3系统一键root方法&#xff01; [复制链接] 青青子衿198976青青子衿198976注册时间2011-9-26最后登录2012-9-15在线时间730 小时阅读权限150积分3996帖子1173精华32UID13306151版主 在线时间730 小时经验1629 分贡献2693 点极币10442 极币最后登录2012-9…

creator图片循环显示_CocosCreator背景图循环播放

以前在玩小游戏的时候发现有的小游戏背景图一直再动&#xff0c;视觉效果挺好&#xff0c;给人一种炫炫的感觉&#xff0c;让我这写后台的码农很是羡慕和膜拜。没想到天意弄人&#xff0c;我也开始写游戏前端了刚接触CocosCreator,好多东西都不懂&#xff0c;整个懵逼状态&…

完全卸载oracle11g步骤

1、 开始&#xff0d;&#xff1e;设置&#xff0d;&#xff1e;控制面板&#xff0d;&#xff1e;管理工具&#xff0d;&#xff1e;服务 停止所有Oracle服务。2、 开始&#xff0d;&#xff1e;程序&#xff0d;&#xff1e;Oracle - OraHome81&#xff0d;&#xff1e;Oracl…

PyCharm安装开发游戏的Pygame

方式一&#xff1a;利用PyCharm导入Pygame包 通常情况下&#xff0c;Pygame可以通过Pycharm的单击菜单File-->Settings...&#xff0c;弹出Settings窗口&#xff0c;在左侧栏中选择Project ***&#xff08;此处***是你的当前项目名&#xff09;-->Project Interpreter&a…

Jsp-Servlet 概要总结[转]

Servlet三个要素: 1.必须继承自HttpServlet 2.必须实现doGet()或者doPost() 3.必须在web.xml中配置Servlet <servlet> <servlet-name> </servlet-name> <servlet-class> </servlet-class> </servlet><servlet-mapping> <servlet-…

php函数学习二

rename():修改文件的名字 addcslashes(&#xff09;&#xff1a;过滤用户提交的敏感字符&#xff0c;一般通过转义提高安全性 dechex():把十进制数据转化为十六进制数据 Abs: 取得绝对值。 Acos: 取得反余弦值。 ada_afetch: 取得资料库的传回列。 ada_autocommit: 开关自动更…

sybase数据库导出mysql_使用BCP从Sybase远程数据库中导出数据

1.在本机安装Sybase ASE 15&#xff0c;我装的开发版全套&#xff0c;懒得去仔细看需要哪个了2.在Sybase安装目录里找到ini\sql.ini&#xff0c;在里面添加数据源例如&#xff1a;[MYDS]masterNLWNSCK,192.168.1.201,5000queryNLWNSCK,192.168.1.201,5000其中MYDS是数据源名称&…

Web项目,要求:保存用户名和密码在Cookie中,下次登录不再重新输入

设计一个实现登录功能的Web项目&#xff0c;要求&#xff1a;保存用户名和密码在Cookie中&#xff0c;下次登录不再重新输入 var cookie {};//设置 cookie.SetCookiesfunction(name,value,exptime){ try{ if(arguments.length 2) return arguments.callee(…

Pycharm使用black作为Python代码格式化外部工具

Pycharm菜单Code->Reformat Code能对Python代码进行格式化&#xff0c;但是black能进一步规范格式&#xff0c;它是PEP8的严格子集。 本次操作的相关环境信息如下&#xff1a;Pycharm 2018版&#xff0c;Python3.6,&#xff08;注意&#xff0c;写本文时的black只支持在Pyt…

WCF的学习资源

这一两天开始学习WCF&#xff0c;两天前我对WCF一无所知&#xff0c;现在也所知甚少&#xff0c;不过倒是在网上找到了一些学习WCF的不错的资源&#xff0c;在这里收录整理如下&#xff1a;1、http://www.cnblogs.com/jillzhang/tag/WCF/博主张玉彬&#xff0c;其对分布式应用程…

python --函数

转http://www.cnblogs.com/vamei/archive/2012/06/01/2529500.html 函数最重要的目的是方便我们重复使用相同的一段程序。 将一些操作隶属于一个函数&#xff0c;以后你想实现相同的操作的时候&#xff0c;只用调用函数名就可以&#xff0c;而不需要重复敲所有的语句。 函数的定…

mysql slave 线程 简书_【MySQL】你真的读懂了slave status吗?

前言:大家平时在检查主从复制的时候基本上都会使用 show slave status来看主从复制的情况&#xff0c;那么你真的读懂每个指标项了吗&#xff1f;一、status指标解读rootlocalhost [(none)]>show slave status\GERROR 2006 (HY000): MySQL server has gone awayNo connectio…

Python中用input()和print()体现输入输出重定向

众所周知&#xff0c;在Python中&#xff0c; 语句&#xff1a;变量input() 的功能是&#xff1a;从键盘读取数据到内存变量&#xff0c;此过程为输入。此时&#xff0c;键盘为标准输入设备&#xff0c;对应的文件对象名为sys.stdin。 语句&#xff1a;input(变量) 的功能是&…

【DI专题】在 DI 脚本文件中调用存储过程

以前用过&#xff0c;但是隔很久不用&#xff0c;还是会有点忘记&#xff0c;还是记下来吧&#xff1a;&#xff09; 1.在左侧datastore区域&#xff0c;选择数据库&#xff0c;选择 Function,单击右键&#xff0c;选择 import by name; 2.在弹出对话框中&#xff0c;输入待导入…