所谓的值传递(pass-by-value)指的是:传递给方法的是参数值的一个copy。Java方法使用的永远是值传递(很多地方说到的“引用传递”其实也可以看做是值传递,概念搞多了反而还不好理解,干脆说死一点,Java就只使用值传递)。
通过例子来看:
public class Test {
public static void change(String s) {
s = "changed";
}
public static void main(String[] args) {
String s = "original";
change(s);
System.out.println(s); // Output: original
}
}
值传递的示意图如下:
由于String是immutable class,即:String对象一旦创建,就不可修改。所以:
String s = "original";
s = "changed";
应该看成:
String s = new String("original");
s = new String("changed");
即s = "changed"并不是把"original"对象修改成"changed",而是新建了一个"changed"对象,而且于此同时"original"对象依然存在。亦即不应该看成下面这种表示:
String s = new String("original");
s.setValue("changed");
正因为String是个不可变类,所以在change()方法中,参数s指向"original",而s的拷贝指向"changed",s的拷贝的行为对s没有影响,所以System.out.println(s)还是打印出"original"。
下面是一个StringBuffer的例子:
public class Test {
public static void change(StringBuffer sb) {
sb.replace(0, sb.length(), "changed");
}
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("original");
change(sb);
System.out.println(sb.toString()); // Output: changed
}
}
sb.replace(0, sb.length(), "changed"),或者更准确地说应该是copyOfSb.replace(0, sb.length(), "changed")并没有创建新的对象,而是修改了原有的对象,所以System.out.println(sb.toString())打印出来的是changed。
题外话:一般说来,String和基本类型都是immutable class,而StringBuffer、Date还有数组都是可变类。
2010-7-6补充:用final来修饰方法的参数可以强制禁止参数的拷贝指向新的对象,例如:
public class Test {
public static void change(final String s) {
s = "changed"; // 非法!!!
}
public static void main(String[] args) {
String s = "original";
change(s);
System.out.println(s);
}
}
这里final就可以禁止copy of String s指向新对象"changed"的行为:
2011.10.23 补充:
对参数来说,可以分三类:(1)基本类型 primitive type;(2)可变类对象reference;(3)不可变类对象reference。(2)(3)的情况上面已经讨论过了,那么基本类型的情况如何呢?
基本类型的情况有一点特殊。基本类型和reference都是在栈上的值,只是reference存的是堆上对象的地址值,而基本类型存的是本身的值。如下图所示:
当 (i,j) 作为参数传入时,j会被原样copy一份,这份copy仍然指向Integer(10);i也会被原样copy一份,值仍然为5。如下图所示:
所以此时在方法里改变 (i,j) 的值,其实对 (i, j) 并没有什么影响:
当方法执行完毕,堆栈内容和方法执行前没有变化。
可以总结一下,java的值传递是在栈上进行的,即将栈上的primitive type或是reference copy一份,再传递给方法,方法实际操作的是这份copy。这份copy能否影响到堆上的值,要看方法具体对copy的操作是啥,如果是setter,那肯定改变了堆置,如果是new,其实不会改变。
2011.10.26 补充:
联系到【== 与 Object.equals() 的区别】,我们是否可以认为:【== 比较的是栈上的两个值是否相等】?
分享到:
相关推荐
NULL 博文链接:https://aoyi.iteye.com/blog/659179
NULL 博文链接:https://aoyi.iteye.com/blog/631929
0X0E中学算术前置知识0X0D数学库函数正文有了三角函数、反三角函数、对数函数、求幂运算,中学阶段涉及的所有具体的数值计算基本就都可以求解。求此表达式的值:第
0X2B循环for前置知识0X29再谈循环正文Lua除了while和repeat语句还提供了一种for循环语句.while和repeat语句循环终止条件可以是任
目录图例Stage1 入门Stage2 基础Stage3 字符串处理Stage4 理解函数Stage5 表结构Stage6 流程控制Stage7 模块Stage
1. 度量脚本执行时间 2. 记录时间 3. 计算时间间隔
域的定义如果交换环还额外满足以下条件,则称为域:乘法单位元和加法单位元不相等(1不等于0)。由于存在乘法逆元,就意味着可以进行“除法”,所以有的书上也把域称作
安全运营相关文章本篇整理一些安全运营相关的高质量文章[2] 体系化的WAF安全运营实践, 安全研究与实践,
NULL 博文链接:https://aoyi.iteye.com/blog/723571
Outlook 2010发送邮件时弹出错误(0x8004010F).
STM8S207中断系统##pragma 0x原因.pdf,介绍中断的
Outlook 2003/2007 连接exchange2010 报 “0x8004010f 操作失败,找不到某个对象” 错误
#1 0x00002b9405e45e5f in _L_lock_4026 () from /lib64/libc.so.6 #2 0x00002b9405e42df1 in free () from /lib64/libc.so.6 #3 0x00002b9405e5b148 in tzset_internal () from /lib64/libc.so.6 #4 0x00002b9405e5...
最新单片机仿真 将数据0x0f写入AT24C02再读出送P1口显示最新单片机仿真 将数据0x0f写入AT24C02再读出送P1口显示最新单片机仿真 将数据0x0f写入AT24C02再读出送P1口显示最新单片机仿真 将数据0x0f写入AT24C02再读出送...
#define up 0x4800 #define down 0x5000 #define left 0x4b00 #define right 0x4d00 #define esc 0x011b #define enter 0x1c0d #define A 0x1e61 #define S 0x1f73 #define D 0x2064 #define W 0x1177 #define space...
Java 对象搜索器 | java内存对象搜索辅助工具 肖像画家 肖像画家 肖像画家 0x01 工具简介 ############################################################# Java Object Searcher v0.01 author: c0ny1 github: ...
349-将数据0x0f写入AT24C02再读出送P1口显示(51单片机C语言实例Proteus仿真和代码)349-将数据0x0f写入AT24C02再读出送P1口显示(51单片机C语言实例Proteus仿真和代码)349-将数据0x0f写入AT24C02再读出送P1口显示(51...
本人现在用的,一个比较好用的java反编译工具,需要的可以下。
MRS R1,CPSR BIC R1,R1,#0x1F ORR R1,R1,#0x1B MSR CPSR_cxsf,R1
Win7 Win10更新错误0x8024402f解决办法.pdfWin7 Win10更新错误0x8024402f解决办法.pdfWin7 Win10更新错误0x8024402f解决办法.pdfWin7 Win10更新错误0x8024402f解决办法.pdfWin7 Win10更新错误0x8024402f解决办法....