这个很容易理解的。题一中:
1. String a=new String("test"); 此时a指向String对象test。
2. public static void passStr(String test) 此时test和a一样都指向String对象test。
3. test+=" passed"; 因为String对象相加是会重新生成另一个String对象,所以此时test就指向重新生成对象test passed。而a仍然指向String对象test。题二中:
1. TestObject a=new TestObject("test"); 此时a指向TestObject对象。
2. public static void passStr(TestObject test) 此时test和a一样都指向TestObject对象。
3. test.setStr(test.getStr()+" passed"); 此时test仍然和a一样都指向TestObject对象。
1. String a=new String("test"); 此时a指向String对象test。
2. public static void passStr(String test) 此时test和a一样都指向String对象test。
3. test+=" passed"; 因为String对象相加是会重新生成另一个String对象,所以此时test就指向重新生成对象test passed。而a仍然指向String对象test。题二中:
1. TestObject a=new TestObject("test"); 此时a指向TestObject对象。
2. public static void passStr(TestObject test) 此时test和a一样都指向TestObject对象。
3. test.setStr(test.getStr()+" passed"); 此时test仍然和a一样都指向TestObject对象。
第二个例子之所以改变了参数的值,是因为它可访问转换器方法!
首先要解决术语的问题,最适合“按值传递”的看起来是自变量。“按值传递”以及它的含义取决于如何理解程序的运行方式。最常见的意思是获得要传递的任何东西的一个本地副本,但这里真正的问题是如何看待自己准备传递的东西。对于“按值传递”的含义,目前存在两种存在明显区别的见解:
(1) Java按值传递任何东西。若将基本数据类型传递进入一个方法,会明确得到基本数据类型的一个副本。但若将一个句柄传递进入方法,得到的是句柄的副本。所以人们认为“一切”都按值传递。当然,这种说法也有一个前提:句柄肯定也会被传递。但Java的设计方案似乎有些超前,允许我们忽略(大多数时候)自己处理的是一个句柄。也就是说,它允许我们将句柄假想成“对象”,因为在发出方法调用时,系统会自动照管两者间的差异。
(2) Java主要按值传递(无自变量),但对象却是按引用传递的。得到这个结论的前提是句柄只是对象的一个“别名”,所以不考虑传递句柄的问题,而是直接指出“我准备传递对象”。由于将其传递进入一个方法时没有获得对象的一个本地副本,所以对象显然不是按值传递的。Sun公司似乎在某种程度上支持这一见解,因为它“保留但未实现”的关键字之一便是byvalue(按值)。但没人知道那个关键字什么时候可以发挥作用。
尽管存在两种不同的见解,但其间的分歧归根到底是由于对“句柄”的不同解释造成的。我打算在本书剩下的部分里回避这个问题。大家不久就会知道,这个问题争论下去其实是没有意义的——最重要的是理解一个句柄的传递会使调用者的对象发生意外的改变。
(1) Java按值传递任何东西。若将基本数据类型传递进入一个方法,会明确得到基本数据类型的一个副本。但若将一个句柄传递进入方法,得到的是句柄的副本。所以人们认为“一切”都按值传递。当然,这种说法也有一个前提:句柄肯定也会被传递。但Java的设计方案似乎有些超前,允许我们忽略(大多数时候)自己处理的是一个句柄。也就是说,它允许我们将句柄假想成“对象”,因为在发出方法调用时,系统会自动照管两者间的差异。
(2) Java主要按值传递(无自变量),但对象却是按引用传递的。得到这个结论的前提是句柄只是对象的一个“别名”,所以不考虑传递句柄的问题,而是直接指出“我准备传递对象”。由于将其传递进入一个方法时没有获得对象的一个本地副本,所以对象显然不是按值传递的。Sun公司似乎在某种程度上支持这一见解,因为它“保留但未实现”的关键字之一便是byvalue(按值)。但没人知道那个关键字什么时候可以发挥作用。
尽管存在两种不同的见解,但其间的分歧归根到底是由于对“句柄”的不同解释造成的。我打算在本书剩下的部分里回避这个问题。大家不久就会知道,这个问题争论下去其实是没有意义的——最重要的是理解一个句柄的传递会使调用者的对象发生意外的改变。
对,根据运行结果当然很容易推导出你的观点来。但是否意味着除String外的所有的类都象TestObject传递??
to pcdos(流浪)
"方法传递的都是地址!!只是java中对象都是按引用来传递的,所以方法传递对象时就像是按引用传递的",那就是说,java里除了基本类型外都是按照按引用传递的??那对参数的操作都会修改其原来的值????
to : alphazhao(绿色咖啡):
那究竟是按值传递还是按引用传递?????这问题应该还是比较重要的吧???
若将String看做是一个对象,那么它同样传递是一个String类型的句柄副本,这就是为什么String test传进去直接相加也不会影响main方法内的test值的原因。
TestObject传递的也是一个副本,若TestObject可以做针对TestObject句柄本身而不是其下的变量String a;做操作,同样不会影响到main方法内的TestObject变量。将所有的class都看做对象,包括String基础class,那么从句柄的方向来说,java可是说是按引用传递的,针对传递的参数(实例中passStr(String test)和passStr(TestObject test)中的两个test参数对象)对象本身做处理,是不会对原本的实参进行任何处理,但是若是对这个参数(实际上是副本)所对应的引用对象(比如TestObject test其下的String a变量)做操作,就会有影响,因为它和main()方法内的TestObject test(原本,针对副本而言)两者对应的String a是同一个对象。
也许我讲得过于罗嗦和不明了,希望你能明白
因为String的内容是不能改变的,你给它赋新值的时候,实际上是产生了一个新的String句柄来指向新值。
>>那就是说,java里除了基本类型外都是按照按引用传递的??
是的。
简单的说 第一各字母大写的类传引用
我明白你的意思,那这样的话,也就是说,传递后产生的副本及其原来的对象其中的内容是指向同一个地址???即虽然句柄不一样,但两个句柄具体的内容指向的是同一个具体的String???不对吧,既然有了句柄的副本,那应该有了对象本身的完全副本才对呀,按照你的理解,这个副本可能仅仅是一个名字代表而已,只不过是取了另一个名字,而其实际内容仍是原来的??而实际上我们要操作的大部份可能是这个副本的具体内容,而不是其名称而已。
to MrYoucheng(老大)、namowen(寒号不已):
可以确认”java里除了基本类型外都是按照按引用传递的“吗??我觉得不对(按照我的理解,应该都是按值传递的)
这么说吧:
将变量看做是一把“钥匙”,java的基础变量比如int,float等和String类对应的变量都是没有匹配“锁”的钥匙,因为尽管这些变量同样可以看做是一个class类的句柄,而普通的class变量则看做是有匹配“锁”的“钥匙”。传递到方法内部的参数都是“钥匙的副本”,对于int,String等类的钥匙而言,你的例子中:
public static void passStr(String test)
{
test+=" passed";
System.out.println(test);
}
此时,改变的就是这个“钥匙的副本”本身,和原本的钥匙是不相关的,也就是说原本的钥匙并不会因为这个方法的运行而变动;
对于其它的类而言,在你的例子中,这两个方法是不同的操作。
public static void passStr(TestObject test)
{
test.setStr(test.getStr()+" passed";
System.out.println(test.getStr());
}
此时传递进去的参数test同样是“钥匙的副本”,如果方法内改变的是test本身(即假如test也可直接+,如:test += "pass";),那么自然和上面一样,但是,方法内改动不是test这个“钥匙的副本”,改变的是这个“钥匙的副本”所对应的锁(此处即指TestObject类下的String a变量)。现在就明了了,对于普通的class参数对象而言,“钥匙”和“钥匙的副本”所对应的“锁”是同一个,所以你改变了“钥匙的副本”对应的锁,也就是改变了“钥匙”对应的锁。这回你应该明白了吧!!
应该这么说:java里除了基本类型和Stirng类型外都是按引用传递的!!
1、对象是传引用的
2、参数是传值的
这两个能够同时成立吗?一个字:是!在java中,你从来没有传递对象,你传递的仅仅是对象的引用!
一句话,java是传引用的。然而,当你传递一个参数,那么只有一种参数传递机制:传值!
通常,当程序员讨论传值和传引用时,他们是指语言的参数传递机制,c++同时支持这两种机制,
因此,以前使用过c++的程序员开始好像不能确定的java是如何传参数的。java语言为了事情变得简单只支持参数传值的机制。
java中的变量有两种类型:引用类型和原始类型。当他们被作为参数传递给方法时,他们都是传值的。
这是一个非常重要的差别,下面的代码范例将说明这一点。在继续前,我们有必要定义一下传值和传引用。
传值意味着当参数被传递给一个方法或者函数时,方法或者函数接收到的是原始值的副本。
因此,如果方法或者函数修改了参数,受影响的只是副本,原始值保持不变。
关于java中的参数传递的混乱是因为很多java程序员是从c++转变过来的。c++有引用和非引用类型的变量,
并且分别是通过传引用和传值得。java语言有原始类型和对象引用,那么,按照逻辑,java对于原始类型使用传值而对引用是传引用的,
就像c++一样。毕竟,你会想到如果你正在传递一个引用,那么它一定是传引用的。这是一个很诱惑人的想法,但是是错误的!
在c++和java中,当函数的参数不是引用时,你传递的是值得副本(传值)。但是对于引用类型就不同了。在c++中,当参数是引用类型,
你传递的是引用或者内存地址(传引用),而在java中,传递一个引用类型的参数的结果只是传递引用的副本(传值)而非引用自身。
这是一个非常重要的区别!java不考虑参数的类型,一律传递参数的副本。仍然不信?如果java中是传引用,那么下面的范例中的swap
方法将交换他们的参数。因为是传值,因此这个方法不是像期望的那样正常工作。
class Swap
{
public static void main(String args[])
{
Integer a, b;
int i,j;
a = new Integer(10);
b = new Integer(50);
i = 5;
j = 9;
System.out.println("Before Swap, a is " + a);
System.out.println("Before Swap, b is " + b);
swap(a, b);
System.out.println("After Swap a is " + a);
System.out.println("After Swap b is " + b);
System.out.println("Before Swap i is " + i);
System.out.println("Before Swap j is " + j);
swap(i,j);
System.out.println("After Swap i is " + i);
System.out.println("After Swap j is " + j);
}
public static void swap(Integer ia, Integer ib)
{
Integer temp = ia;
ia = ib;
ib = temp;
}
public static void swap(int li, int lj)
{
int temp = li;
li = lj;
lj = temp;
}
} 上面程序的输出是: Before Swap, a is 10
Before Swap, b is 50
After Swap a is 10
After Swap b is 50
Before Swap i is 5
Before Swap j is 9
After Swap i is 5
After Swap j is 9 因为swap方法接收到的是引用参数的副本(传值),对他们的修改不会反射到调用代码。译者注:在传递引用和原始类型时还是有不同的,考虑以下的代码:
class Change
{
public static void main(String args[])
{
StringBuffer a=new StringBuffer("ok");
int i;
i = 5;
System.out.println("Before change, a is " + a);
change(a);
System.out.println("After change a is " + a);
System.out.println("Before change i is " + i);
change(i);
System.out.println("After change i is " + i);
}
public static void change(StringBuffer ia)
{
ia.append(" ok?");
}
public static void change(int li)
{
li = 10;
}
}程序的输出为:Before change, a is ok
After change a is ok ok?
Before change i is 5
After change i is 5即如果传递的是引用,那么可以修改引用对象的内容,这个改变会影响到原来的对象,而传递的如果是原始类型则不会有影响。
这个也是造成误解的原因之一吧。
你的意思是本身及其副本的具体内容是同一个对象,即副本及其本身所指向的“锁”是同一个,我没理解错吧???
to hhjgx(何躝):
你的结论很好,但我想知道的是方法调用时何时为近按值,何时按引用传递???这个才是最最关键的。
所以在你的例子里面 public static void passStr(String test)
{
test+=" passed";
System.out.println(test);
}
这个改变的是"钥匙的副本",因此不会影响"钥匙"本身
而
public static void passStr(TestObject test)
{
test.setStr(test.getStr()+" passed";
System.out.println(test.getStr());
}
中改变的的是"钥匙的副本"所对应的"锁"中的对象,即TestObject类下的String a变量。
我老觉得这个解释怪怪的,请多多联系[email protected]
方法传递的都是值,而对象都是按引用传递,所以方法传递对象时就像是按引用
传递,如果传递的是基本类型,就是传值了回复人: pcdos(流浪) ( ) 信誉:110 2002-9-9 17:21:11 得分:0 方法传递的都是地址!!
只是java中对象都是按引用来传递的,所以方法传递对象时就像是按引用传递的