java获取对象引用个数_java对象引用-要掌握的细节

hello ,好久没来了。

今天我来和大家分享一下有关引用变量的注意事项,一是加深一下自己的理解,二是对这块不太理解的同学可以看看。

大神可飘过,有什么不对或不足的地方请多多指教,谢谢。

假设场景:

有一个统计游戏玩家信息调查问卷系统,玩家填写了调查问卷,会给玩家一些奖励,当然目前这不是我们关注的部分。

我们需要记录一下玩家的姓名,年龄,邮箱,以及玩家曾经玩过的游戏有哪些。

既然要记录玩家玩过的游戏,必然要有Game类:

packageindi.bruce.summary;public classGame {private int id; //随便填写一个id

private String name; //总要有个游戏名字吧

private String developer; //游戏是谁开发的

private String type; //游戏总要有个类型吧 ,例如:策略,体育,动作等等

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}publicString getDeveloper() {returndeveloper;

}public voidsetDeveloper(String developer) {this.developer =developer;

}publicString getType() {returntype;

}public voidsetType(String type) {this.type =type;

}

}

现在定义玩家类 Player:

packageindi.bruce.summary;importjava.util.ArrayList;importjava.util.List;public classPlayer {private int id ; //玩家编号

private String name; //姓名

private int age; //年龄

private String email; //邮箱

private List gameList; //曾经玩过的游戏,便于分析用户行为

public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public intgetAge() {returnage;

}public void setAge(intage) {this.age =age;

}public ListgetGameList() {if(gameList == null){return new ArrayList();

}returngameList;

}publicString getEmail() {returnemail;

}public voidsetEmail(String email) {this.email =email;

}

}

正题开始:

假设场景1:玩家问卷数据已经存库,玩家要修改自己的信息,而系统需要记录一下到底修改了哪些地方。

1)从数据库读取用户的数据Player。

2)将原来的对象player复制出来一份给temp对象,玩家修改信息在temp对象上修改(既然要记录玩家修改了什么,则需要原来的对象和现在的对象对比)。

3)两个对象做一下对比,就可以做操作记录了。

场景1测试代码:

@Test

public void sceneOne(){

Player player = getPlayer(1110); //从数据库获取的对象

System.out.println("print player.getName() is:"+player.getName());

Player temp = player; //玩家修改信息全部在副本temp上操作,这样就可以对比到底玩家修改了什么信息,哈哈哈....

temp.setName("moon"); //玩家修改了名字

System.out.println("print temp.getName() is:" + temp.getName()); //哈哈...成功了,多简单的事情

System.out.println("print player.getName() is:" + player.getName());

/*但是打印结果

* print player.getName() is:sky

* print temp.getName() is:moon

* print player.getName() is:moon

*

* 疑问:为什么只是修改temp属性name的值,而player的name值也变了呢?

*/

}

//假设该方法是从数据库获取该用户的数据对象,这不是我们目前关注的部分

public Player getPlayer(int id){

Player player = new Player();

player.setId(1110);

player.setName("sky");

player.setAge(20);

player.setEmail("brucetest@indi.com");

return player;

}

为什么会出现上面的情况呢,来分析一下引用变量的工作原理:

77d33fefdeb53a3873697fc42cb75a04.png

1.代码中"Player player = getPlayer(1110);"做了两件事:

1)将玩家1110数据从数据库数据库读出来(这部分假设从数据库读出来),并加载的堆内存中(player对象实际上只存在堆内存中)。

2)新建一个引用变量player(其实就是指针)指向堆内存的player对象(也就是记录堆内存中player的内存地址)

2.代码"Player temp = player;"做了一件事:

新建引用变量temp,并且指向堆内存中的player对象。

总结:所以不管是针对栈中的引用变量temp,还是栈中的引用变量player操作,实际上都是操作堆内存中的player对象。

注意:解决场景1出现的问题,需要引入一个概念"深拷贝",概念请问度娘.

解决方案:1)首先Player类需要实现Cloneable接口:public class Player implements Cloneable

2)需要在Player中重写Object的clone方法

public Object clone(){

Object obj = null;

try {

return super.clone();

} catch (CloneNotSupportedException e) {

e.printStackTrace();

}

return obj;

}

3)在调用的地方:Player player = getPlayer(1110);Player temp = (Player)player.clone();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值