这段代码的主要部分调用了两个很相近的方法,changeObj()和changePri()。唯一不同的是它们一个把对象作为输入参数,另一个把Java中的基本类型int作为输入参数。并且在这两个函数体内部都对输入的参数进行了改动。看似一样的方法,程序输出的结果却不太一样。changeObj()方法真正的把输入的参数改变了,而changePri()方法对输入的参数没有任何的改变。从这个例子知道Java对对象和基本的数据类型的处理是不一样的。和C语言一样,当把Java的基本数据类型(如int,char,double等)作为入口参数传给函数体的时候,传入的参数在函数体内部变成了局部变量,这个局部变量是输入参数的一个拷贝,所有的函数体内部的操作都是针对这个拷贝的操作,函数执行结束后,这个局部变量也就完成了它的使命,它影响不到作为输入参数的变量。这种方式的参数传递被称为"值传递"。而在Java中用对象的作为入口参数的传递则缺省为"引用传递",也就是说仅仅传递了对象的一个"引用",这个"引用"的概念同C语言中的指针引用是一样的。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。除了在函数传值的时候是"引用传递",在任何用"="向对象变量赋值的时候都是"引用传递"。如:package reference;
class PassObj
{
    String str = "init value";
}
public class ObjPassValue 
{    public static void main(String[] args) 
    {
        PassObj objA = new PassObj();
        PassObj objB = objA;        objA.str = "changed in objA";
        System.out.println("Print objB.str value: " + objB.str);
    }
}
/* RUN RESULT
Print objB.str value: changed in objA
*/
 

解决方案 »

  1.   

    第一句是在内存中生成一个新的PassObj对象,然后把这个PassObj的引用赋给变量objA,第二句是把PassObj对象的引用又赋给了变量objB。此时objA和objB是两个完全一致的变量,以后任何对objA的改变都等同于对objB的改变。即使明白了Java语言中的"指针"概念也许还会不经意间犯下面的错误。Hashtable真的能存储对象吗?看一看下面的很简单的代码,先是声明了一个Hashtable和StringBuffer对象,然后分四次把StriingBuffer对象放入到Hashtable表中,在每次放入之前都对这个StringBuffer对象append()了一些新的字符串:package reference;
    import java.util.*;
    public class HashtableAdd{
        public static void main(String[] args){
            Hashtable ht = new Hashtable();
            StringBuffer sb = new StringBuffer();
            sb.append("abc,");
            ht.put("1",sb);     
            sb.append("def,");
            ht.put("2",sb);
            sb.append("mno,");
            ht.put("3",sb);
            sb.append("xyz.");
            ht.put("4",sb);
            
            int numObj=0;
            Enumeration it = ht.elements();
            while(it.hasMoreElements()){
                System.out.print("get StringBufffer "+(++numObj)+" from Hashtable: ");
                System.out.println(it.nextElement());
            }
        }
    }
     
      

  2.   

    如果你认为输出的结果是:
    get StringBufffer 1 from Hashtable: abc,
    get StringBufffer 2 from Hashtable: abc,def,
    get StringBufffer 3 from Hashtable: abc,def,mno,
    get StringBufffer 4 from Hashtable: abc,def,mno,xyz.那么你就要回过头再仔细看一看上一个问题了,把对象时作为入口参数传给函数,实质上是传递了对象的引用,向Hashtable传递StringBuffer对象也是只传递了这个StringBuffer对象的引用!每一次向Hashtable表中put一次StringBuffer,并没有生成新的StringBuffer对象,只是在Hashtable表中又放入了一个指向同一StringBuffer对象的引用而已。对Hashtable表存储的任何一个StringBuffer对象(更确切的说应该是对象的引用)的改动,实际上都是对同一个"StringBuffer"的改动。所以Hashtable并不能真正存储能对象,而只能存储对象的引用。也应该知道这条原则对与Hashtable相似的Vector, List, Map, Set等都是一样的。上面的例程的实际输出的结果是:/* RUN RESULT
    get StringBufffer 1 from Hashtable: abc,def,mno,xyz.
    get StringBufffer 2 from Hashtable: abc,def,mno,xyz.
    get StringBufffer 3 from Hashtable: abc,def,mno,xyz.
    get StringBufffer 4 from Hashtable: abc,def,mno,xyz.
    */
     类,对象与引用Java最基本的概念就是类,类包括函数和变量。如果想要应用类,就要把类生成对象,这个过程被称作"类的实例化"。有几种方法把类实例化成对象,最常用的就是用"new"操作符。类实例化成对象后,就意味着要在内存中占据一块空间存放实例。想要对这块空间操作就要应用到对象的引用。引用在Java语言中的体现就是变量,而变量的类型就是这个引用的对象。虽然在语法上可以在生成一个对象后直接调用该对象的函数或变量,如:new String("Hello NDP")).substring(0,3)  //RETURN RESULT: Hel