一、前言

  首先先说结论,Java中方法参数传递方式是按值传递。如果参数是基本类型,传递的是基本类型的字面量值的拷贝。如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。

  接下来深入了解一下为什么是值传递,要想知道Java到底是传值还是传引用,首先要知道基本类型和引用类型的区别。

二、深入了解参数传递

  1.基本类型 和 引用类型的不同之处

基本类型包括8种数据类型:int、short、long、byte、char、float、double、boolean,在方法中定义的非全局基本数据类型变量的具体内容是存储在栈中的;除了基本类型以外的都是引用类型:类、接口类型、数组类型、字符串类型都是引用类型,引用类型变量其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址(字符串类型比较特殊,涉及到字符串常量池,这里不做深入研究)。

示例:

int num = 10;      
String str = new String("hello");

注:该图的堆区是经过简化的,实际的情况会复杂点,这里只作示意

如图所示,num是基本类型,值就直接保存在变量中。而str是引用类型,变量中保存的只是实际对象的地址。一般称这种变量为"引用",引用指向实际对象,实际对象在堆中并保存着实际内容。

  2.赋值运算符(=)的作用

num = 20;
str = "world";
注:该图的堆区是经过简化的,实际的情况会复杂点,这里只作示意
 
对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变。如上图所示,"world" 字符串对象没有被改变。(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)。
  3.值传递和引用传递的区别
值传递是指在调用函数时将实际参数复制一份传递到函数中,引用传递是指在调用函数时将实际参数的地址直接传递到函数中,所以值传递和引用传递的根本区别是是否会复制一份副本。
  4.实例
  例子一(基本数据类型):  
public static void main(String[] args) {
Test test = new Test(); int i = 10;
test.print(10);
System.out.println("main方法输出i:" + i);
} public void print(int j) {
j = 20;
System.out.println("print方法输出j:" + j);
}

  结果:

print方法输出j:20
main方法输出i:10

这个例子应该还是很好理解的,test.print(10)将10作为参数传给print方法, 将10拷贝一份给 j,修改 j 不会影响 i 。

  例子二(引用数据类型):

public static void main(String[] args) {
Test test = new Test();
User user = new User();
user.setName("Tom");
user.setAge("18");
test.print(user);
System.out.println("main方法输出用户:" + user);
} public void print(User user1) {
user1.setName("Mike");
System.out.println("print方法输出用户:" + user1);
}

  结果:

print方法输出用户:User{name="Mike",age="18"}
main方法输出用户:User{name="Mike",age="18"}

  解释: test.print(user)将user对象的引用(即user对象的内存地址)拷贝一份给形参的user1,也就是说main方法中的user引用和print方法的user1引用都指向堆中的同一个user对象,所以user1修改user对象的数据,user的也会相应的改变。

  user1.setName("Mike")执行前

  user1.setName("Mike")执行后

注意:引用数据类型中的字符串类型比较特殊,String被设计成为了不可变类型,为String赋值时不会覆盖以前的对象而是引用一个新的字符串对象(如果新的字符串在常量池中直接返回其引用,否则创建一个字符串对象,详情可以去我的另一篇博客浅析Java常量池 - pluto_blog - 博客园 (cnblogs.com)),在这里我们不考虑新字符串在常量池的情况。

  下面来看各String类型的例子:
public static void main(String[] args) {
Test test = new Test();
String name = new String("Tom");
test.print(name);
System.out.println("main方法输出name:" + name);
} public void print(String name1) {
name1 = "Mike";
System.out.println("print方法输出name1:" + name1);
}

  结果:

print方法输出name1:Mike
main方法输出name:Tom

  解释:由于String被设计成为了不可变类型,为name赋值时不会覆盖以前的对象而是创建一个新的字符串对象并返回引用。

  name1 = "Mike"执行前

  name1 = "Mike"执行后

三、总结

Java中方法参数传递方式是按值传递。如果参数是基本类型,传递的是基本类型的数据拷贝。如果参数是引用类型,因为栈中存的是对象的地址值,所以传递的是该参量所引用的对象在堆中地址值的拷贝,除了特殊的String类型,形参对象可以影响实参对象的值。

Java的参数传递是值传递还是引用传递?的更多相关文章

  1. java中方法的参数传递机制(值传递还是引用传递)

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

  2. java参数传递时到底是值传递还是引用传递

    java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...

  3. java中参数传递--值传递,引用传递

    java中的参数传递——值传递.引用传递   参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用. ...

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

    当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递? 答:是值传递.Java 语言的参数传递只有值传递.当一个实例对象作为参数被传递到方法中时,参 ...

  5. java中值传递和引用传递

    最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  6. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

  7. JavaScript 函数参数传递到底是值传递还是引用传递

    tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...

  8. Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结

    这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...

  9. Java是值传递还是引用传递?

    Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...

随机推荐

  1. 【动画消消乐 】HTML+CSS 吃豆豆动画 073

    前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出-   自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...

  2. Java 中节省 90% 时间的常用的工具类

    前言 你们有木有喜欢看代码的领导啊,我的领导就喜欢看我写的代码,有事没事就喜欢跟我探讨怎么写才最好,哈哈哈...挺好. 今天我们就一起来看看可以节省 90% 的加班时间的第三方开源库吧,第一个介绍的必 ...

  3. 记录21.07.23 —— Vue.js基础(二)

    Vue基础(二) 过滤器 过滤器作用 全局过滤器 输出结果 私有过滤器 输出结果 把其中一个做点修改 错误信息 自定义指令 全局自定义指令 私有自定义指令 钩子函数 注意:fond-weight是粗细 ...

  4. CF474D Flowers 题解

    题目:CF474D Flowers 传送门 DP?递推? 首先可以很快看出这是一道 DP 的题目,但与其说是 DP,还不如说是递推. 大家还记得刚学递推时教练肯定讲过的一道经典例题吗?就是爬楼梯,一个 ...

  5. Android Jetpack 架构组件最佳实践之“网抑云”APP

    背景 近几年,Android 相关的新技术层出不穷.往往这个技术还没学完,下一个新技术又出来了.很多人都是一脸黑人问号? 不少开发者甚至开始哀嚎:"求求你们别再创造新技术了,我们学不动了!& ...

  6. Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

    Spring Cloud Stream 简介 在微服务的开发过程中,可能会经常用到消息中间件,通过消息中间件在服务与服务之间传递消息,不管你使用的是哪款消息中间件,比如RabbitMQ.Kafka和R ...

  7. 如何让win10开机默认开启小键盘?

    如何让win10开机默认开启小键盘? windows10默认是关闭小键盘的.每次输入开机密码的时候都需要按一下小键盘开启键(numlock),才能按数字键 一.运行注册表编辑器,修改InitialKe ...

  8. CSS Transform完全指南 #flight.Archives007

    Title/ CSS Transform完全指南 #flight.Archives007 序: 第7天了! 终身学习, 坚持创作, 为生活埋下微小的信仰. 我是忘我思考,共同进步! 简介: 一篇最简约 ...

  9. 【笔记】numpy.array的常用基本运算以及对数据的操作

    numpy.array的基本运算以及对数据的操作 设置一个问题,例如 这种只需要基本的运算就可以实现 类似的 numpy对向量的运算进行了优化,速度是相当快的,这种被称为universal funct ...

  10. Kurento实战之二:快速部署和体验

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...