class Obj{
String str = "init value";
public String toString(){
return str;
}
}
public class ObjRef{
Obj aObj = new Obj();
int aInt = 11;
public void changeObj(Obj inObj){
inObj.str = "changed value";
}
public void changePri(int inInt){
inInt = 22;
}
public static void main(String[] args)
{
ObjRef oRef = new ObjRef();
System.out.println("Before call changeObj() method: " + oRef.aObj);
oRef.changeObj(oRef.aObj);
System.out.println("After call changeObj() method: " + oRef.aObj);
System.out.println("==================Print Primtive=================");
System.out.println("Before call changePri() method: " + oRef.aInt);
oRef.changePri(oRef.aInt);
System.out.println("After call changePri() method: " + oRef.aInt);
}
}
/* RUN RESULT
Before call changeObj() method: init value
After call changeObj() method: changed value
==================Print Primtive=================
Before call changePri() method: 11
After call changePri() method: 11
*
*/
从这个例子知道Java对对象和基本的数据类型的处理是不一样的。和C语言一样,当把Java的基本数据类型(如int,char,double等)作为入口参数传给函数体的时候,传入的参数在函数体内部变成了局部变量,这个局部变量是输入参数的一个拷贝,所有的函数体内部的操作都是针对这个拷贝的操作,函数执行结束后,这个局部变量也就完成了它的使命,它影响不到作为输入参数的变量。这种方式的参数传递被称为"值传递"。而在Java中用对象的作为入口参数的传递则缺省为"引用传递",也就是说仅仅传递了对象的一个"引用",这个"引用"的概念同C语言中的指针引用是一样的。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。
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());
}
}
}
/* 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. */ 结果很明显不可以
class UnCloneA {
private int i;
public UnCloneA(int ii) { i = ii; }
public void doubleValue() { i *= 2; }
public String toString() {
return Integer.toString(i);
}
}
class CloneB implements Cloneable{
public int aInt;
public UnCloneA unCA = new UnCloneA(111);
public CloneB clone(){
CloneB o = null;
try{
o = (CloneB)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
}
public class CloneMain {
public static void main(String[] a){
CloneB b1 = new CloneB();
b1.aInt = 11;
System.out.println("before clone,b1.aInt = "+ b1.aInt);
System.out.println("before clone,b1.unCA = "+ b1.unCA);
CloneB b2 = (CloneB)b1.clone();
b2.aInt = 22;
b2.unCA.doubleValue();
System.out.println("=================================");
System.out.println("after clone,b1.aInt = "+ b1.aInt);
System.out.println("after clone,b1.unCA = "+ b1.unCA);
System.out.println("=================================");
System.out.println("after clone,b2.aInt = "+ b2.aInt);
System.out.println("after clone,b2.unCA = "+ b2.unCA);
}
}
/** RUN RESULT:
before clone,b1.aInt = 11
before clone,b1.unCA = 111
=================================
after clone,b1.aInt = 11
after clone,b1.unCA = 222
=================================
after clone,b2.aInt = 22
after clone,b2.unCA = 222
*/
(要了解深度Clone,请自已去查找相关资料,基实就是在上面例子中让CloneA也实现在Cloneable这个接口)
class CloneC implements Cloneable{
public String str;
public StringBuffer strBuff;
public CloneC clone(){
CloneC o = null;
try{
o = (CloneC)super.clone();
}catch(CloneNotSupportedException e){
e.printStackTrace();
}
return o;
}
}
public class StrClone {
public static void main(String[] a){
CloneC c1 = new CloneC();
c1.str = new String("initializeStr");
c1.strBuff = new StringBuffer("initializeStrBuff");
System.out.println("before clone,c1.str = "+ c1.str);
System.out.println("before clone,c1.strBuff = "+ c1.strBuff);
CloneC c2 = (CloneC)c1.clone();
c2.str = c2.str.substring(0,5);
//个人对于下面结论四中的蓝色部分感觉有问题。试写如下代码,注释掉前面那句。
c2.str = "hello"; //如果真如他所说,那这里的改变应该影响到c1.str的输出,但实际没有。。而如果我们写如下代码:
CloneC c3 = c1;
c3.str = "hello i'm c3 here"; //则输出的结果只对c1有影响,c2.str没有变,也就是说c2真正实现在跟基本数据类型一样的Clone,而不是一个引用!!!我不知道我是不是理解对了,但他的解释是肯定错掉了,还请那位达达来解释哈!
c2.strBuff = c2.strBuff.append(" change strBuff clone");
System.out.println("=================================");
System.out.println("after clone,c1.str = "+ c1.str);
System.out.println("after clone,c1.strBuff = "+ c1.strBuff);
System.out.println("=================================");
System.out.println("after clone,c2.str = "+ c2.str);
System.out.println("after clone,c2.strBuff = "+ c2.strBuff);
}
}
/* RUN RESULT
before clone,c1.str = initializeStr
before clone,c1.strBuff = initializeStrBuff
=================================
after clone,c1.str = initializeStr
after clone,c1.strBuff = initializeStrBuff change strBuff clone
=================================
after clone,c2.str = initi
after clone,c2.strBuff = initializeStrBuff change strBuff clone
*
*/
----------------解决方案--------------------------------------------------------
对象引用和基本数据类型在栈上分配...而对象在堆上分配..
如果类里有基本数据类型的话,那么分配栈内存的时候,相当与是C中的一个结构体..
入口是对象引用的地址..
CloneC c3 = c1, c3这个对象引用就是c1.2者除了名字不同,其余的完全一致的..
clone一个对象时,对象引用是处于不同的栈空间,除了基本数据之外,指向同一个堆内存.
c3.str = "hello i'm c3 here"; 那么等于是c3.str指向了"hello i'm c3 here";
但是c3.str先前指向的字符串呢?它仍然在堆内存中,因为String是final...
c1和c3是同一个引用,,c2则不是..
所以c2.str仍然指向开始的那个字符串..而c1和c3是同一个引用,所以c1.str就是c3.str..
所以被改变了...
呵呵,不知道俺说的对不对,俺也只是在学java前学过一个月c....
----------------解决方案--------------------------------------------------------
楼上的文章不错,建议初学者仔细体会体会
----------------解决方案--------------------------------------------------------
别光看啊 也对我的问题发表下意见啊
----------------解决方案--------------------------------------------------------
你没有问题啊,不错啊,见解也挺好啊
----------------解决方案--------------------------------------------------------
----------------解决方案--------------------------------------------------------
不要脸红,确实是不错的
好好努力吧
----------------解决方案--------------------------------------------------------
呵呵 最近本来是学JSP 结果没学到什么。。。到是复习以前的东西。。
看到这 感觉不错 就帖上来了 希望能对新人有帮助
----------------解决方案--------------------------------------------------------
学JAVA不能好高骛远,先把J2SE打扎实了再说
----------------解决方案--------------------------------------------------------
'白发老爹'说的对!一定要好好琢磨!第三天开始!
----------------解决方案--------------------------------------------------------