测试思路

每个更改形参的方法,返回值都是void,不同方法的参数设置不同类型。

注意在方法内测地址的时候在改之前测一下,才能看出传入参数是不是传了地址。(注意反正OS的内存地址是虚拟的,JVM中的也是,掰扯不清的,所以就姑且按照JVM中的虚拟地址来考虑吧)

数组参数传递

private static void changeArray(int[] array) {Arrays.fill(array, 2);
}

数组的值改变了,但地址没变,是引用传递。

基本类型及其包装类的参数传递

private static void changeInt(int data) {data = 3;
}private static void changeInteger(Integer data) {data = 3;
}

无论是int还是Integer,没有返回值,所以外面的实参值没变。

对于基本类型,打印地址也能看出地址改了,是值传递。
对于包装类型,打印地址能看出地址没改,是引用传递。

由于hashCode()被重写了,所以可以用System.out.println(System.identityHashCode(data));来看虚拟地址(当然不是真的地址啦)。

普通类参数传递

private static class Person {int id;String name;int age;Person(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';}
}private static void changePerson(Person data) {data = new Person(101, "Bob", 15);
}

是引用类型,也是引用传递。打印地址测试过,确实在new之前的虚拟地址与传入实参的虚拟地址一致。(想测地址就把@Override的toString()注释掉,再打印对象啊)

只改属性

private static void changePersonAttributes(Person data) {data.id = 101;data.name = "Bob";data.age = 15;
}

改了属性,打印结果改了,但是实际地址没改,说明是引用传递。

完整代码

部分打印地址的测试内容就删掉不附上了,感兴趣可以自测。

import java.util.Arrays;public class ReferenceTest {private static void changeArray(int[] array) {Arrays.fill(array, 2);}private static void changeInt(int data) {data = 144;}private static void changeInteger(Integer data) {data = 155;}private static class Person {int id;String name;int age;Person(int id, String name, int age) {this.id = id;this.name = name;this.age = age;}@Overridepublic String toString() {return "Person{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';}}private static void changePerson(Person data) {data = new Person(101, "Bob", 15);}private static void changePersonAttributes(Person data) {data.id = 101;data.name = "Bob";data.age = 15;}public static void main(String[] args) {int[] array = new int[5];System.out.println(Arrays.toString(array));changeArray(array);System.out.println(Arrays.toString(array));Integer a = 133;changeInteger(a);System.out.println(a);changeInt(a);System.out.println(a);Person p = new Person(100, "Sam", 10);System.out.println(p);changePerson(p);System.out.println(p);changePersonAttributes(p);System.out.println(p);}
}

测试结果

[0, 0, 0, 0, 0]
[2, 2, 2, 2, 2]
133
133
Person{id=100, name='Sam', age=10}
Person{id=100, name='Sam', age=10}
Person{id=101, name='Bob', age=15}

总结反思

其实自己也一直没搞明白Java的参数传递到底是值传递还是引用传递,网上说法众说纷纭,于是下定决心自己认真测一下。

按照JVM的虚拟地址来做测试,在整数测试的时候还考虑了整数缓存池,选了127以上的数。

个人认为,其实不能单纯利用返回值为void的函数运行后查看原值来判断是值传递还是引用传递。我选择在传完参数后的函数内测地址,地址一样就是引用传递,不一样就是值传递。
hashCode()一般包含了地址,但Integer的hashCode()则只是原值,得使用System.identityHashCode(data)来测。

emmm,接下来,讲讲结论orz

总结

  • 基本类型是值传递
  • 引用类型是引用传递,返回值为void的话未必能在外面看到改变。
    • 引用类型对象重新被new了以后,看不到改变;但改变属性能看到改变。
    • 数组也是引用类型,数组元素值的改变能在void方法外面测出来。

其实研究这个问题Real迷惑,如有不足还请指正!


Update on 2020.3.7
强调String这个问题,如果你简单地测试得到地址没变,这是不对的,涉及到String常量池等等……
因为我还不太会,所以回头再来补充orz

看来这篇文章可能有些我思虑不周(尚未涉猎)的地方啊,果然水深莫涉啊orz

【Java】探究Java方法的参数传递是值传递还是引用传递相关推荐

  1. java面试题:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?

    java面试题:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答:是值传递.Java编程语言只有值传递参数. 当一个对象实 ...

  2. Java中,String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?...

    <Java中,String类型和包装类型作为参数传递时,是属于值传递还是引用传递呢?> <Java中的值传递和引用传递> 原理知识: 如果参数类型是原始类型,那么传过来的就是这 ...

  3. Java中的参数传递,到底是值传递还是引用传递?

    文章内容为转载,转载自公众号Hollis关于我要彻底给你讲清楚,Java就是值传递,不接受争辩的那种! 原文链接:我要彻底给你讲清楚,Java就是值传递,不接受争辩的那种! 知乎回答链接:Java 到 ...

  4. Java参数传递(值传递还是引用传递)

    文章目录 基本类型和引用类型的区别 下面我们再来看看==的作用 值传递和引用传递的区别 基本类型作为参数传递 对象作为参数传递 关于String 参考资料 基本类型和引用类型的区别 int num = ...

  5. java中的就近原则、方法中值传递和引用传递的区别、什么是构造方法、this关键字用法、什么是封装

    你知道java中的就近原则嘛? package com.Test.java; /*** * 在java里面有一个"就近原则"详情可以参照下面代码**/public class Ac ...

  6. java中的参数传递(只有值传递没有引用传递)

    Java中只有传值调用(值传递),没有传址调用(址传递或者引用传递).所以在java方法中改变参数的值是不会改变原变量的值的,但为什么改变引用变量的属性值却可以呢?请看下面的解答. java中的数据类 ...

  7. 这一次,彻底解决Java的值传递和引用传递

    本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...

  8. Java值传递和引用传递详细说明(详细分析)

    1. 形参与实参 我们先来重温一组语法: 形参:方法被调用时需要传递进来的参数,如:func(int a)中的a,它只有在func被调用期间a才有意义,也就是会被分配内存空间,在方法func执行完成后 ...

  9. Java值传递和引用传递详细说明

    本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...

最新文章

  1. 沉浸式小说App获得200万美元投资
  2. [转载]深入理解JavaScript闭包(closure)
  3. 某pl/sql培训练习题
  4. SAP Spartacus User form通过label标签的实现原理
  5. java switch case怎么判断范围_【转】Java期末复习攻略!
  6. php教程目录,php基础入门篇-文件和目录操作_PHP教程
  7. numpy 最大值_第 85 天:NumPy 统计函数
  8. 从零开始编写深度学习库(二)FullyconnecteLayer CPU编写
  9. @开发者,这个 GitHub 项目可以褥羊毛!
  10. Mono喜迁新家-http://www.xamarin.com/
  11. 复杂UI的组织-创建者模式-uitableview思想
  12. Java编译出现不可映射字符
  13. Java实现 LeetCode 313 超级丑数
  14. ActiveMQ在win7下启动失败解决方案
  15. tp获取php异常信息,ThinkPHP 异常处理
  16. APP全栈工程师修炼之路(三)
  17. 微信“跳一跳”外挂制作历程
  18. 北京理工大学计算机科学与技术培养方案,王全玉_北京理工大学计算机学院
  19. fatal: unable to access ‘‘: Failed to connect to 27.0.0.1 port 7890 after 2097 ms:Connection
  20. nginx-quic

热门文章

  1. 【MM系列】SAP 关于更改物料的价格控制类型
  2. about-ie下模拟input file上传功能失效
  3. PHP json_encode
  4. NET 下数据库图片的存入与读取
  5. 图像水平梯度和竖直梯度代码_Opencv图像处理(三)
  6. 计算机专业刚毕业本科生,计算机专业应届本科毕业生自我鉴定
  7. zabbix yum安装
  8. RPC和REST区别
  9. 机器学习笔记(七)——决策树模型
  10. 手把手教你做用户画像