欢迎关注WX公众号:
Java之函数值传递和对象传递
文章链接:http://blog.csdn.net/qq_16628781/article/details/72810012
知识点:
- 函数传参问题提出;
- 函数传参问题的总结;
- 实例讲解给函数传基本数据类型和对象;
- 新名词记录{Java函数传值和传递引用}
概览
在我们写函数的时候,我们经常需要传递参数进去,但是传参这里却是有个不太令人注意的大学问,如果不能好好理解,那么出现一些会令你“意想不到”的怪事。
未能正确的理解传参的问题,就会导致一些人为很奇怪的现象出现。例如,有次在项目中,传递了一个List类型的参数,但是很奇怪的是,每次执行那个方法之后,在函数外面的那个list对象被置空了。
那时候一直都没有想到是什么问题导致的。今天特意搜寻了下关于Java函数传参的问题,才理解了这个问题。
先来一个总结。
总结
Java的参数传递中,分为值传递和引用传递。(很多人说后面一个是对象传递,但是Java中,一切皆对象,还是说引用传递比较好),下面先来一个总结:
- 如果传递如果是基本数据类型传值,对形参的修改不会影响实参。
- 如果传递的是非基本数据类型,例如包装类型对象,那么形参和实参指向同一个内存地址(同一个对象),所以对形参的修改会影响到实参的属性。
解释1:基本的数据类型包括,byte,short,int,long,double,char,string以及他们的包装类型。他们是不可改变的数据类型了。
解释2:非基本数据类型包括,list,stringbuffer,以及自定义的实体类都属于非基本数据类型。
实例讲解
- 传递基本数据类型int
//ParamsPass类的方法
public void paramPassTest1(Integer a) {
a = 20;
System.out.println(TAG + ": " + a);
}
//调用上面的方法
ParamsPass paramsPass = new ParamsPass();
Integer a = new Integer(99);
paramsPass.paramPassTest1(a);
System.out.println(TAG + a);
执行上面的方法,看到传递的int类型实参在函数内部被调用了,外面的a的值没有改变。结果如下图所示:
- 传递对象
userbean实体类
public class UserBean implements Serializable {
//串行化版本统一标识符
private static final long serialVersionUID = 1L;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
//1、测试方法
public void paramPassTest2(UserBean userBean) {
System.out.println("inside_func_userbean_hashcode: " + userBean.hashCode());
userBean.setPassword("000000");
System.out.println("inside_func_userbean_password: " + userBean.getPassword());
}
//2、调用测试方法
ParamsPass paramsPass = new ParamsPass();
UserBean userBean = new UserBean();
userBean.setPassword("123456");
System.out.println("outside_func_before_Password: " + userBean.getPassword());
System.out.println("outside_func_before_hashcode: " + userBean.hashCode());
paramsPass.paramPassTest2(userBean);
System.out.println("outside_func_after_Password: " + userBean.getPassword());
System.out.println("outside_func_after_hashcode: " + userBean.hashCode());
在上面中,传入了一个userbean实体类对象,初始设置的密码是“123456”,然后在里面,将密码改成“000000”;最后将在外面的userbean对象和传入到函数里面的对象的hashcode打印出来,结果居然是同一个地址,由此说明传递对象的是一个对象的引用,在方法里面进行修改对象的参数,会将引用的对象进行修改。
- 传入list对象
//userbean和上面的是一样的,这里省略了
//测试方法,打印hashcode和值
public void paramPassTest3(List<String> list) {
System.out.println("inside_func_hashcode: " + list.hashCode());
list.add("other value");
System.out.println("inside_func_after_added_size: " + list.size());
list.clear();
System.out.println("inside_func_after_cleared_size: " + list.size());
}
//调用上面的测试方法
List<String> stringList = new ArrayList<>();
stringList.add("value1");
stringList.add("value2");
System.out.println("outside_func_before_hashcode: " + stringList.hashCode());
System.out.println("outside_func_before_size: " + stringList.size());
paramsPass.paramPassTest3(stringList);
System.out.println("outside_func_after_size: " + stringList.size());
System.out.println("outside_func_after_hashcode: " + stringList.hashCode());
结果如下图所示:
可以看到打印输出,两个对象是同一个对象,所以传递list对象的时候,传递的也是对象的引用,对形参list对象进行操作,同时也会影响外面实参的属性。因为list已经不是一个基本的数据类型了。
同理的,stringbuffer,stringBuilder也是如此。
伪总结
说了这么多了,在开始提出的那个疑问,就得到解决了。这里就不再啰嗦了,总结在前面已经写了。
以上那个就是所有内容,如有任何问题,请及时与我联系,谢谢。