Java之函数值传递和对象传递

来源:互联网 发布:淘宝用红包退款 编辑:程序博客网 时间:2024/05/21 15:42

Java之函数值传递和对象传递

文章链接:http://blog.csdn.net/qq_16628781/article/details/72810012

知识点:

  1. 函数传参问题提出;
  2. 函数传参问题的总结;
  3. 实例讲解给函数传基本数据类型和对象;

4. 新名词记录{Java函数传值和传递引用}

概览

在我们写函数的时候,我们经常需要传递参数进去,但是传参这里却是有个不太令人注意的大学问,如果不能好好理解,那么出现一些会令你“意想不到”的怪事。

未能正确的理解传参的问题,就会导致一些人为很奇怪的现象出现。例如,有次在项目中,传递了一个List类型的参数,但是很奇怪的是,每次执行那个方法之后,在函数外面的那个list对象被置空了。

那时候一直都没有想到是什么问题导致的。今天特意搜寻了下关于Java函数传参的问题,才理解了这个问题。

先来一个总结。

总结

Java的参数传递中,分为值传递和引用传递。(很多人说后面一个是对象传递,但是Java中,一切皆对象,还是说引用传递比较好),下面先来一个总结:

  1. 如果传递如果是基本数据类型传值,对形参的修改不会影响实参。
  2. 如果传递的是非基本数据类型,例如包装类型对象,那么形参和实参指向同一个内存地址(同一个对象),所以对形参的修改会影响到实参的属性。

解释1:基本的数据类型包括,byte,short,int,long,double,char,string以及他们的包装类型。他们是不可改变的数据类型了。

解释2:非基本数据类型包括,list,stringbuffer,以及自定义的实体类都属于非基本数据类型。

实例讲解

  1. 传递基本数据类型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的值没有改变。结果如下图所示:
    结果截图

  2. 传递对象

    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打印出来,结果居然是同一个地址,由此说明传递对象的是一个对象的引用,在方法里面进行修改对象的参数,会将引用的对象进行修改。
    结果截图

  3. 传入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也是如此。

伪总结

说了这么多了,在开始提出的那个疑问,就得到解决了。这里就不再啰嗦了,总结在前面已经写了。

以上那个就是所有内容,如有任何问题,请及时与我联系,谢谢。