JAVA基础(Java参数传值还是传引用)
参数是按值传递而不是按引用传递,也就是说Java应用只有一种参数传递机制,就是按值传递。写这篇文章是为了揭穿一个广为流传的神话,即Java应用程序通过引用传递参数,以避免因依赖“通过引用传递”的行为而导致的常见编程错误。
这个节选的一些反馈表明,我把这个问题搞混了,或者完全搞错了。很多不同意我的读者用C++语言做例子。因此,在本专栏中,我将使用C++和Java应用程序来进一步澄清一些事实。
重要
看完所有评论,问题终于水落石出了。大测试提示:至少在一个主要问题上有困惑。因为对象是通过引用传递的。对象确实是通过引用传递的;摘录和这个不冲突。摘录说所有的参数都是通过值传递的——另一个参数。以下说法是正确的:在Java应用程序中,永远不会传递对象,只会传递对象引用。因此,对象是通过引用传递的。但是区分参数是如何传递的是很重要的,这也是这篇摘录的目的。Java应用程序通过引用传递对象并不意味着Java应用程序通过引用传递参数。参数可以是对象引用,而Java应用程序通过值传递对象引用。
c++和Java应用中的参数传递
Java应用中的变量可以是以下两种类型之一:引用类型或基本类型。当作为参数传递给方法时,这两种类型以相同的方式处理。这两种类型都是通过值传递的;没有一个是引用传递的。这是一个重要的功能,如下面的代码示例所示。
在继续讨论之前,定义术语“按值传递”和“按引用传递”很重要。按值传递意味着当一个参数被传递给一个函数时,该函数接收原始值的一个副本。因此,如果函数修改了该参数,只有副本会被更改,而原始值将保持不变。通过引用传递意味着当一个参数传递给一个函数时,该函数接收原始值的内存地址,而不是该值的副本。因此,如果函数修改了该参数,调用代码中的原始值也会改变。
以上很重要。请注意以下结论。以上是以上文章的精髓和最终结论,我认为:
1。对象通过引用传递
2。Java应用只有一种参数传递机制,即按值传递
3。按值传递意味着当参数被传递时,函数接收原始值的副本
4。通过引用传递意味着当一个参数传递给一个函数时,该函数接收原始值的内存地址,而不是值的副本
。首先我们来看第一点:对象是通过引用传递的
。的确,我认为你对此没有任何疑问。示例:
class test 01
{
public static void main(string[]args)
{
string buffers = new string buffer(" good ");
string buffer S2 = s;
s2.append("下午好。");
system . out . println(s);
}
}
对象S和s2在内存中指向同一个地址,所以它们指向同一个对象。
如何解释“对象通过引用传递”?
这里的意思是对象的引用是在对象赋值操作过程中传递的,所以对象是通过引用传递的。有什么问题吗?
程序的输出是:
下午好。
这说明s2和S是同一个对象。
这里要澄清一点,这里的传递对象其实是一个传递值,因为对象是指针,而这个赋值是指针之间的赋值,所以在java里叫做传递引用。(引用的是什么?不是地址吗?地址是什么,不过只是一个整数值)
看下面的例子:
class test 02
{
public static void main(string[]args)
{
int I = 5;
int I2 = I;
I2 = 6;
system . out . println(I);
}
}
程序的结果是什么?5!!!
这是什么意思?原来的数据类型是传值的,这个传值也是指赋值的行为。下一个问题:Java应用的参数传递机制只有一个,即
class test 03
{
public static void main(string[]args)
{
string buffers = new string buffers(" good ")
string buffer S2 = new string buffer(" bad ");
测试(s,S2);
system . out . println(s);//9
system . out . println(S2);//10
}
静态void测试(StringBuffer s,string buffer S2){
system . out . println(s);//1
system . out . println(S2);//2
S2 = s;//3
s = new string buffer(" new ");//4
system . out . println(s);//5
system . out . println(S2);//6
s . append(" hah ");//7
S2 . append(" hah ");//8
}
}
程序的输出是:
good
bad
new
good hah
bad[/br
这里需要强调的是“参数传递机制”,它不同于赋值语句时的传递机制。
我们看到1和2处的输出完全符合我们的预期
3点s2到S,4点S到一个新的对象
所以5的输出打印了新创建的对象的内容,而6打印的原始S的内容
7和8修改了对象内容,但是为什么9和10的输出是那样的呢?
Java应用中只有一种参数传递机制,即按值传递。
到目前为止,我想总结一下我对这个问题的最终看法和一个我认为可以帮助你理解的方法:
我们可以把java中的对象理解为c/c++中的指针
比如在c/c++中:
int * p;
打印(p);//1
* p = 5;
print(* p);//2
1打印的结果是什么,一个十六进制的地址,2打印的结果是什么?5,也就是指针所指的位置。
即使在c/c++中,这个指针实际上也是一个32位整数。我们可以把我的价值理解为一个long。
而java中对象s是什么也是指针和int整数(对于JVM来说)。我们直接使用它(即s2=s),但System.out.print(s)是个例外。因为实际摇入system . out . print(s . tostring())对象时是一个int整数,这样既可以解释赋值的引用,也可以解释参数的取值(两种情况下都是直接使用),而我们在s.XXX的情况下,s实际上是c/c++中*s的使用。这种在不同用例下的不同结果,是java为我们做的一种简化,但对于c/c++程序员来说,可能是一种误导。java中有很多基于上下文的自动识别和处理的情况。以下有点极端:
class t
{
public static string t = " t ";
public static void main(String[]args)
{
t t = new t();
t . t();
}
static void t(){
system . out . println(t);
}
}
(对于根据上下文自动识别的内容,感兴趣的人可以以后看看我们翻译的java规则)
1 .对象通过引用传递
2。Java应用只有一个参数传递机制,就是传值
3。按值传递意味着当一个参数传递给一个函数时,该函数接收原始值的副本
4。通过引用传递意味着当一个参数传递给一个函数时,该函数接收原始值的内存地址。而不是复制值
,可以总结为三句话:
1。该对象是一个引用
2。原始类型是值
3。String类型需要特殊处理,因为它不提供修改自身的函数,并且每个操作都会生成一个新的String对象。可以认为是及格值。
0条评论