为什么Java只有值传递?
形参和实参
形式参数,是在方法定义阶段,是定义某个函数时使用的参数,用于接收实参传入。例f(x,y)中x和y是形参。
实际参数,是在方法调用阶段,是主调函数调用有参函数时,实际传递的内容。例f(3,7)中3和7是实参。
值传递和引用传递
值传递和引用传递不是简单地通过传递内容区分的。如果是值,就是值传递;如果是引用,就是引用传递。这一理解是不正确的。
值传递,是指在调用函数时将实际参数复制一份传递给函数形参。此时,在函数中对形参做修改,不影响实际参数。
引用传递,是指在调用函数时将实际参数的地址直接传递给函数形参。此时,在函数中对参数做修改,将影响实际参数。
根本区别在于值传递会创建副本,因此函数中无法改变原始对象;引用传递不创建副本,函数中可以改变原始对象。
通过一个经典案例讲解Java值传递
public class ParamPassing {
private static int intStatic = 222;
private static String stringStatic = "old string";
private static StringBuilder stringBuilderStatic = new StringBuilder("old stringBuilder");
public static void main(String[] args) {
// 方法调用1
method(intStatic);
System.out.println(intStatic);
// 方法调用2
method();
System.out.println(intStatic);
// 方法调用3
method(stringStatic);
System.out.println(stringStatic);
// 方法调用4
method(stringBuilderStatic, stringBuilderStatic);
System.out.println(stringBuilderStatic);
}
// 方法1
public static void method(int intStatic) {
intStatic = 777;
}
// 方法2
public static void method() {
intStatic = 888;
}
// 方法3
public static void method(String stringStatic) {
stringStatic = "new string";
}
// 方法4
public static void method(StringBuilder stringBuilderStatic1, StringBuilder stringBuilderStatic2) {
stringBuilderStatic1.append(".method.first-");
stringBuilderStatic2.append(".method.second-");
// 引用重新赋值
stringBuilderStatic1 = new StringBuilder("new stringBuilder");
stringBuilderStatic1.append("new method's append");
}
}
运行结果:
222
888
old string
old stringBuilder.method.first-.method.second-
方法1,参数是局部变量,拷贝的变量值是777,会存入虚拟机栈中的局部变量表的第一个位置。在方法内部,根据作用于就近原则,使用局部变量的参数,操作与实参无关。而方法2,先把本地赋值的888压入虚拟机栈中的操作栈,然后给静态遍历intStatic赋值。

方法3,String是immutable对象,类中没有提供任何方法用来修改对象。“old string"仍然由实参持有,在方法3中,会重新new一个String对象,并把引用赋给形参。
方法4,直接使用参数引用,可以修改对象;当对引用重新赋值后,不再影响实参。
当stringBuilderStatic引用作为实参传递给形参stringBuilderStatic1时,此时形参是stringBuilderStatic的一个副本,两个引用共同指向StringBuilder对象所在的堆内存地址,此时对形参的任何修改都会改变对象属性。当创建新对象并赋值给stringBuilderStatic1后,该引用指向了新的内存地址,对其修改不会改变原对象的属性。
字节码解释
0: aload_0 // 引用类型入栈
1: ldc #14 // 将常量值从常量池推到栈顶
// String .method.first-
3: invokevirtual #15 // 调用实例方法
// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
6: pop // 栈顶元素出栈
14: new #17 // 创建实例
// class java/lang/StringBuilder
17: dup // 赋值栈顶数值,压入栈顶
18: ldc #18
// String new stringBuilder
20: invokespecial #19 // 实例初始化
// Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
23: astore_0 // 将栈中ref引用存到局部变量表
24: aload_0 // 加载局部变量到操作数栈
25: ldc #20 // 加载常量到操作数栈
// String new method's append
27: invokevirtual #15 // 调实例方法
// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: pop // 操作数栈顶元素出栈
31: return // 方法返回指令
为什么Java只有值传递?的更多相关文章
- Java 为值传递而不是引用传递
——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...
- java的值传递笔记
1. 背景:开发小伙伴突然问我java是值传递还是引用传递,我说当然是值传递,只不过有时候传递一个对象时实际传递的是对象的地址值,所以让人容易产生一种引用传递的假象,貌似在李刚的疯狂java讲义有提到 ...
- java是值传递还是引用传递
首先写一个简便的Employee,以便测试使用. class Employee { private String name; public Employee(String name) { this.n ...
- Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结
这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...
- java面试3-对于java中值传递的理解(Hollis)
这是根据Hollis的直面java内容习得(有兴趣的可以加他微信公众号) 对于初学者来说,要理解java中的值传递很难理解,为什么说java只有值传递?那引用传递呢? java中的错误理解: 错误理解 ...
- Java是值传递还是引用传递?
Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...
- 堆栈详解 + 彻底理解Java的值传递和引用传递
本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...
- java的值传递机制
一.练习:编写Java程序,将二维数组中的行列互调显示出来. 代码1为自己编写: package com.xxgpra.CH6; public class Hangliehudiao_pra4 { p ...
- Java只有值传递(Java值传递还是引用传递?)
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10830521.html 一:区分Java数据类型.变量类型 Java数据类型分两种:基本数据类型.引用类型. ...
- Java的值传递和引用传递的说法
学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨论的话题又是充满争议:有的论坛帖子说Java ...
随机推荐
- linux没有 conio.h解决的方式
conio.h不是C标准库中的头文件,在ISO和POSIX标准中均未定义. conio是Console Input/Output(控制台输入输出)的简写,当中定义了通过控制台进行数据输入和数据输出的函 ...
- Python+Django+SAE系列教程10-----Django模板
在本章中,我们开始模板,在前面的章节,您可能已经注意到,我们回到文本的方式有点特别的示例视图. 那.HTML直接在硬编码 Python 其中代码. 这的确是一个小BT. def current_dat ...
- windows Hook 消息分类
调用SetWindowsHookEx的DLL的模块实例句柄,它可以经由DllMain入口的第一个参数得到.HHOOK SetWindowsHookEx( int idHook,HOOKPROC lpf ...
- 用树莓派和DS18B20做个汽车温度记录仪
原文:用树莓派和DS18B20做个汽车温度记录仪 用树莓派和DS18B20做个汽车温度记录仪[原创] 很想知道夏日阳光暴晒下,汽车内的最高温度以及温度的变化情况.觉得用树莓派和DS18B20来实现应该 ...
- WPF Layout 系统概述——Measure
原文:WPF Layout 系统概述--Measure 前言 在WPF/Silverlight当中,如果已经存在的Element无法满足你特殊的需求,你可能想自定义Element,那么就有可能会面临重 ...
- Win8 Metro(C#)数字图像处理--2.62图像对数增强
原文:Win8 Metro(C#)数字图像处理--2.62图像对数增强 [函数名称] 对数增强 WriteableBitmap LogenhanceProcess(Writeabl ...
- 未在本地计算机上注册“microsoft.ACE.oledb.12.0” 解决方法
今日写一个浏览Excel文件的代码,忽然发现提示如下错误,表示很惊讶,因为我的另外一台电脑不会,但是这台就包这个异常. 解决方法: 去http://download.microsoft.com/dow ...
- LINQ查询表达式---------join子句
LINQ查询表达式---------join子句 join 子句接受两个源序列作为输入. 每个序列中的元素都必须是可以与另一个序列中的相应属性进行比较的属性,或者包含一个这样的属性. join子句使用 ...
- 实现dropdownList 无刷新
<asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptMana ...
- 数据库连接池之_Druid简单使用
数据库连接池: 连接池是创建和管理一个连接的缓冲池的技术,这些连接真备好被任何需要他们的线程使用,可以对传统的JDBCjava数据库连接()进行优化 在实际开发中,我们需要频繁的操作数据库,这就意味着 ...