关于JAVA中引用及返回值的问题

1.什么是引用?

在《java编程思想》中有这样一段描述:“每种编程语言都有自己的数据处理方式。有些时候,程序员必须注意将要处理的数据是什么类型。你是直接操纵元素,还是用某种基于特殊语法的间接表示(例如C/C++里的指针)来操作对象。所有这些在 Java 里都得到了简化,一切都被视为对象。因此,我们可采用一种统一的语法。尽管将一切都“看作”对象,但操纵的标识符实际是指向一个对象的“引用”(reference)。”

我们先写一个User类,然后我们创建一个User对象:

User user =new User();

user就是User类的一个实例的一个引用,而真正创建的对象是new User()

2.需要注意的地方

可以由多个引用同时指向相同的实例,如

User user=null;

User user1 =new User();

user= user1;

这样user和user1都指向同一个User实例

我们写一个User类、一个Session类和一个Test类再进一步说明

public class User {
private int id;
private String username;
private String password;
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}
public String getUsername() {
    return username;
}
@Override
public String toString() {
    return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
public void setUsername(String username) {
    this.username = username;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
}


import java.util.HashMap;
import java.util.Map;

public class Session {
private Map<String,Object> sessionmap =new HashMap<String, Object>();
public Object getParam(String key){
    return sessionmap.get(key);
    
}


public void setParam(String key,Object value){
sessionmap.put(key, value);
}

}

public class Test {

    public static void main(String[] args){
Session session =new Session(); //创建session对象
User user =new User();//创建User对象
user.setId(123);
user.setUsername("a");
user.setPassword("123456");//设置user对象的参数
session.setParam("user", user);//将user对象放入session对象中
System.out.println(user);//打印
User user0=(User) session.getParam("user");//我们再把User对象从session中拿出来
user0.setId(0);
user0.setPassword(null);
user0.setUsername(null);//清理这个对象的参数
System.out.println(user0);//打印清理后的对象

User user1=(User) session.getParam("user");

System.out.println(user1);然后再打印直接从session中取出的对象

System.out.println(user);//打印user
}

这里的的引用user、user0还有user1其实都是指向同一个对象,也就是在main方法中创建的new User(),在User user=new User()之后,通过session的setParam方法将引用传递给了Session类中的HashMap,HashMap存储了这个引用,所以HashMap中的这个引用和前面的这些引用一样,都是指向相同对象,然后通过getParam()方法返回的实际上是对User的引用。

因此在通过域对象或者是被多类调用的对象储存对象时,应该注意储存对象的引用,尤其是在进行修改此对象的数据时。

关于JAVA中引用及返回值的问题

运行结果:

User [id=123, username=a, password=123456]
User [id=0, username=null, password=null]
User [id=0, username=null, password=null]
User [id=0, username=null, password=null]

我们可以通过org.apache.commons包下的BeanUtils类的cloneBean(Object object)方法实现实例的克隆,这样我们等于复制了一遍原来的实例,这个方法的底层也是通过“new”实现的

3.神奇的集合类

集合存储的实际上是对象的引用,那么如果相同集合存储同一个对象的引用,那么就会出现神奇的现象。
set集合也可以存储“相同”的元素(User类重写equles()和hashCode()方法):

import java.util.HashSet;

import java.util.Set;


public class Test {


public static void main(String[] args){

Set<User> set =new HashSet<User>();

User user=new User();

set.add(user);

user.setId(1);

set.add(user);

user.setPassword("123");

set.add(user);

user.setUsername("aaa");

set.add(user);

System.out.println(set);

 }


}

运行结果:

[User [id=1, username=aaa, password=123], User [id=1, username=aaa, password=123], User [id=1, username=aaa, password=123], User [id=1, username=aaa, password=123]]


在这个set集合中存储的引用实际上是指向同一个对象,造成这样的原因是因为HashSet中的add方法实际上是将该对象以对象的哈希值为键,object类为值存储在一个HashMap中的,而每次修改user对象导致该对象的hash值改变,从而通过add方法存储在HashMap()时每次键都不同,造成了不同的键存储相同的值。

    publicboolean add(Ee) {

        returnmap.put(e,PRESENT)==null;

    }