这个很容易理解的。题一中:
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中对象都是按引用来传递的,所以方法传递对象时就像是按引用传递的
      

  3.   

    按值传递
    首先要解决术语的问题,最适合“按值传递”的看起来是自变量。“按值传递”以及它的含义取决于如何理解程序的运行方式。最常见的意思是获得要传递的任何东西的一个本地副本,但这里真正的问题是如何看待自己准备传递的东西。对于“按值传递”的含义,目前存在两种存在明显区别的见解:
    (1) Java按值传递任何东西。若将基本数据类型传递进入一个方法,会明确得到基本数据类型的一个副本。但若将一个句柄传递进入方法,得到的是句柄的副本。所以人们认为“一切”都按值传递。当然,这种说法也有一个前提:句柄肯定也会被传递。但Java的设计方案似乎有些超前,允许我们忽略(大多数时候)自己处理的是一个句柄。也就是说,它允许我们将句柄假想成“对象”,因为在发出方法调用时,系统会自动照管两者间的差异。
    (2) Java主要按值传递(无自变量),但对象却是按引用传递的。得到这个结论的前提是句柄只是对象的一个“别名”,所以不考虑传递句柄的问题,而是直接指出“我准备传递对象”。由于将其传递进入一个方法时没有获得对象的一个本地副本,所以对象显然不是按值传递的。Sun公司似乎在某种程度上支持这一见解,因为它“保留但未实现”的关键字之一便是byvalue(按值)。但没人知道那个关键字什么时候可以发挥作用。
    尽管存在两种不同的见解,但其间的分歧归根到底是由于对“句柄”的不同解释造成的。我打算在本书剩下的部分里回避这个问题。大家不久就会知道,这个问题争论下去其实是没有意义的——最重要的是理解一个句柄的传递会使调用者的对象发生意外的改变。
      

  4.   

    首先要解决术语的问题,最适合“按值传递”的看起来是自变量。“按值传递”以及它的含义取决于如何理解程序的运行方式。最常见的意思是获得要传递的任何东西的一个本地副本,但这里真正的问题是如何看待自己准备传递的东西。对于“按值传递”的含义,目前存在两种存在明显区别的见解:
    (1) Java按值传递任何东西。若将基本数据类型传递进入一个方法,会明确得到基本数据类型的一个副本。但若将一个句柄传递进入方法,得到的是句柄的副本。所以人们认为“一切”都按值传递。当然,这种说法也有一个前提:句柄肯定也会被传递。但Java的设计方案似乎有些超前,允许我们忽略(大多数时候)自己处理的是一个句柄。也就是说,它允许我们将句柄假想成“对象”,因为在发出方法调用时,系统会自动照管两者间的差异。
    (2) Java主要按值传递(无自变量),但对象却是按引用传递的。得到这个结论的前提是句柄只是对象的一个“别名”,所以不考虑传递句柄的问题,而是直接指出“我准备传递对象”。由于将其传递进入一个方法时没有获得对象的一个本地副本,所以对象显然不是按值传递的。Sun公司似乎在某种程度上支持这一见解,因为它“保留但未实现”的关键字之一便是byvalue(按值)。但没人知道那个关键字什么时候可以发挥作用。
    尽管存在两种不同的见解,但其间的分歧归根到底是由于对“句柄”的不同解释造成的。我打算在本书剩下的部分里回避这个问题。大家不久就会知道,这个问题争论下去其实是没有意义的——最重要的是理解一个句柄的传递会使调用者的对象发生意外的改变。
      

  5.   

    to cuicen_simon(simon):
       对,根据运行结果当然很容易推导出你的观点来。但是否意味着除String外的所有的类都象TestObject传递??
    to pcdos(流浪) 
       "方法传递的都是地址!!只是java中对象都是按引用来传递的,所以方法传递对象时就像是按引用传递的",那就是说,java里除了基本类型外都是按照按引用传递的??那对参数的操作都会修改其原来的值????
    to : alphazhao(绿色咖啡):
       那究竟是按值传递还是按引用传递?????这问题应该还是比较重要的吧??? 
      

  6.   

    本来String类和其它的类的传递就没有什么差别,
    若将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是同一个对象。
    也许我讲得过于罗嗦和不明了,希望你能明白
      

  7.   

    同意cuicen_simon(simon)。
    因为String的内容是不能改变的,你给它赋新值的时候,实际上是产生了一个新的String句柄来指向新值。
    >>那就是说,java里除了基本类型外都是按照按引用传递的??
    是的。
      

  8.   

    int等简单的变量通常是传值的 复杂的变量是穿引用的
    简单的说 第一各字母大写的类传引用
      

  9.   

    to alphazhao(绿色咖啡) :
        我明白你的意思,那这样的话,也就是说,传递后产生的副本及其原来的对象其中的内容是指向同一个地址???即虽然句柄不一样,但两个句柄具体的内容指向的是同一个具体的String???不对吧,既然有了句柄的副本,那应该有了对象本身的完全副本才对呀,按照你的理解,这个副本可能仅仅是一个名字代表而已,只不过是取了另一个名字,而其实际内容仍是原来的??而实际上我们要操作的大部份可能是这个副本的具体内容,而不是其名称而已。
    to MrYoucheng(老大)、namowen(寒号不已):
       可以确认”java里除了基本类型外都是按照按引用传递的“吗??我觉得不对(按照我的理解,应该都是按值传递的)
      

  10.   

    也许是我解释的不够好
    这么说吧:
       将变量看做是一把“钥匙”,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参数对象而言,“钥匙”和“钥匙的副本”所对应的“锁”是同一个,所以你改变了“钥匙的副本”对应的锁,也就是改变了“钥匙”对应的锁。这回你应该明白了吧!!
      

  11.   

    btw:
      应该这么说:java里除了基本类型和Stirng类型外都是按引用传递的!!
      

  12.   

    我觉得各位说得有一定的道理,但不完全,帖上下面这一段论述,我觉得对大家有帮助。完全理解下面的文章,最好是将其中的例子试一下,同时仔细思考。在不同的java新闻组中,参数是传值还是传址一直是一个经常被争辩的话题。误解的中心是以下两个事实:
    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即如果传递的是引用,那么可以修改引用对象的内容,这个改变会影响到原来的对象,而传递的如果是原始类型则不会有影响。
    这个也是造成误解的原因之一吧。
      

  13.   

    to alphazhao(绿色咖啡):
        你的意思是本身及其副本的具体内容是同一个对象,即副本及其本身所指向的“锁”是同一个,我没理解错吧???
    to hhjgx(何躝):
        你的结论很好,但我想知道的是方法调用时何时为近按值,何时按引用传递???这个才是最最关键的。
      

  14.   

    是啊
    所以在你的例子里面      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变量。
      

  15.   

    to alphazhao(绿色咖啡):
        我老觉得这个解释怪怪的,请多多联系[email protected]
      

  16.   

    简单的问题变复杂了,咳!其实很简单,就是:所有类都是按引用传递的,但是,所有的原始类型例如:int,float等及其包装类,例如:Integer,String,都是按值传递的。所以,第一题,显然是值传递。第二题,由于你在参数中使用了一个自定义的类,在passStr中,你操作的其实是类的引用,结果自然是引用传递的效果。
      

  17.   

    同意HHJGX的看法,由于形式上是有传引用和传值的不同,所以产生误解。正是传值的原因,使得JAVA在运行速度上较慢。
      

  18.   

    sorry!!我当时是不是睡着了??!!
    方法传递的都是值,而对象都是按引用传递,所以方法传递对象时就像是按引用
    传递,如果传递的是基本类型,就是传值了回复人: pcdos(流浪) (  ) 信誉:110  2002-9-9 17:21:11  得分:0  方法传递的都是地址!!
    只是java中对象都是按引用来传递的,所以方法传递对象时就像是按引用传递的