Java - 参数传递(传值、传址/引用)

简介: Java - 参数传递(传值、传址/引用)

前言

  在Java中,当对象作为参数传递时,究竟传递的是对象的值,还是对象的引用,这是一个饱受争议的话题。若传的是值,那么函数接收的只是实参的一个副本,函数对形参的操作并不会对实参产生影响;若传的是引用,那么此时对形参的操作则会影响到实参。

Objectobj=newObject();

image.png

在有了上面的基础之后,我们便来看下面这组在网上很流行的例子。

  • 参数传值:基本数据类型 + String类型(即使 String 是一个类)。
  • 参数传址:数组 + 对象。

参数传递 - 基本数据类型

publicclasstest {
publicstaticvoidmain(String[] args) {
inti=1;
System.out.println("before change, i = "+i);
change(i);
System.out.println("after change, i = "+i);
    }
publicstaticvoidchange(inti){
i=5;
    }
}
Console:beforechange, i=1afterchange, i=1

当基本数据类型作为参数传递时,传递的是实参值的副本,即传的是值,无论在函数中怎么操作这个副本,实参的值是不会被改变的。

 

参数传递 - 对象

publicclasstest {
publicstaticvoidmain(String[] args) {
StringBuffersb=newStringBuffer("Hello ");
System.out.println("before change, sb is "+sb.toString());
change(sb);
System.out.println("after change, sb is "+sb.toString());
    }
publicstaticvoidchange(StringBufferstringBuffer){
stringBuffer.append("world !");
    }
}
Console:beforechange, sbisHelloafterchange, sbisHelloworld!

把StringBuffer对象作为参数传递到change函数。 从输出结果中我们可以发现,sb所指向的对象的值被改变了,那么是否我们可以推论出,在Java中,当对象作为参数传递时,传递的是该对象的引用呢?我们再来看下面这个例子:

publicclasstest {
publicstaticvoidmain(String[] args) {
StringBuffersb=newStringBuffer("Hello ");
System.out.println("before change, sb is "+sb.toString());
change(sb);
System.out.println("after change, sb is "+sb.toString());
    }
publicstaticvoidchange(StringBufferstringBuffer){
stringBuffer=newStringBuffer("Hi ");
stringBuffer.append("world !");
    }
}
Console:beforechange, sbisHelloafterchange, sbisHello

如果上面的推论是正确的,即Java中对象作为参数传递,实际传递的是该对象的引用,那么在调用change函数之后,原对象的值应该是会改变的,变为“Hi world !”,但是,当我们运行程序后,结果却是出乎意料。


原对象的值并没有被改变,这与上面的推论相矛盾!为什么在Java中,当对象作为参数传递时,有的时候实参被改变了,而有的时候实参并未被改变呢?下面让我们来分析一下其中的原因:

从文章的开头我们知道,当执行StringBuffer sb = new StringBuffer(“Hello “)时,我们创建了一个指向新建对象“new StringBuffer(“Hello “)”的引用“sb”,如下图所示:

image.png

在第二段代码中,当我们调用change函数后,实际上,形参stringBuffer也指向了实参sb所指向的对象,即:

image.png

那么当我们执行stringBuffer.append(“world !”)后,便通过对象的引用“stringBuffer”修改了对象的值,使之变成了“Hello world !”,即:image.png

但是,在第三段代码中的change函数中,我们又新建了一个对象“new StringBuffer(“Hi “)”(这实际上在内存中开辟了一块在原对象地址之外的新区域),这让形参stringBuffer实际指向了这个新建的对象,并将新对象的值设置为“Hi world !”,即:

image.png

那么我们就不难理解,为何在执行完change函数之后,实参的值仍为“Hello”了。

 

结论

综上所述,我们可以得出结论:在Java中,当对象作为参数传递时,实际上传递的是一份“引用的拷贝”。

目录
相关文章
|
5月前
|
存储 安全 Java
在 Java 中如何将 ArrayList 作为参数传递
【8月更文挑战第23天】
238 0
|
7月前
|
缓存 Java 数据库连接
java面试题目 强引用、软引用、弱引用、幻象引用有什么区别?具体使用场景是什么?
【6月更文挑战第28天】在 Java 中,理解和正确使用各种引用类型(强引用、软引用、弱引用、幻象引用)对有效的内存管理和垃圾回收至关重要。下面我们详细解读这些引用类型的区别及其具体使用场景。
98 3
|
7月前
|
Java
java方法引用::
java方法引用::
|
8月前
|
存储 Java
滚雪球学Java(41):Lambda表达式和方法引用:提高代码可读性和简洁性的神器
【5月更文挑战第16天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
62 2
滚雪球学Java(41):Lambda表达式和方法引用:提高代码可读性和简洁性的神器
|
6月前
|
Java 运维
开发与运维引用问题之软引用又在Java特点如何解决
开发与运维引用问题之软引用又在Java特点如何解决
49 0
|
8月前
|
Java 编译器
滚雪球学Java(34):探究Java方法的神奇魔法和参数传递奥秘
【5月更文挑战第9天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
39 1
滚雪球学Java(34):探究Java方法的神奇魔法和参数传递奥秘
|
7月前
|
数据采集 Java 数据安全/隐私保护
使用Java进行网络采集:代理IP与参数传递详解
Java参数传递是按值传递,包括对象引用的值。当传递对象时,方法内部修改对象内容会影响原始对象,但不能改变原始引用。示例展示了如何在爬虫代理中使用此机制,通过`ProxySettings`类传递代理信息,方法内可访问但不能更改原始对象。理解这一机制对编写高效无错的Java代码至关重要。
使用Java进行网络采集:代理IP与参数传递详解
|
8月前
|
存储 Java 索引
Java一维数组元素的引用与操作技术详解
Java一维数组元素的引用与操作技术详解
90 1
|
7月前
|
Java 数据安全/隐私保护
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
38 0
|
8月前
|
Java
【JAVA学习之路 | 进阶篇】方法引用与构造器引用
【JAVA学习之路 | 进阶篇】方法引用与构造器引用