package MyClasses;class MyClass {
private int myInt;
private Integer myInteger;
private String myString;
public void setInt(int myInt){
this.myInt = myInt;
}
public int getInt(){
return myInt;
}
public void setInteger(Integer myInteger){
this.myInteger = myInteger;
}
public Integer getInteger(){
return myInteger;
}
public void setString(String myString){
this.myString = myString;
}
public String getString(){
return myString;
}
}public class ChangeClass {
public void changeInt(int Int){
Int = 1;
}
public void changeInteger(Integer integer){
integer = new Integer(1);
}
public void changeString(String string){
string = new String("Change string!");
}
public void changeMyClass(MyClass myClass){
myClass.setInt(1);
myClass.setInteger(new Integer(1));
myClass.setString(new String("Change my string!"));
}
public static void main(String[] args) {
int Int;
Integer integer;
String string;
MyClass myClass = new MyClass();
Int = 0;
integer = new Integer(0);
string = new String("String");
myClass.setInt(0);
myClass.setInteger(new Integer(0));
myClass.setString(new String("My string"));
ChangeClass changeClass = new ChangeClass();
changeClass.changeInt(Int);
changeClass.changeInteger(integer);
changeClass.changeString(string);
changeClass.changeMyClass(myClass);
System.out.println(Int);
System.out.println(integer);
System.out.println(string);
System.out.println(myClass.getInt());
System.out.println(myClass.getInteger());
System.out.println(myClass.getString());
}
}
private int myInt;
private Integer myInteger;
private String myString;
public void setInt(int myInt){
this.myInt = myInt;
}
public int getInt(){
return myInt;
}
public void setInteger(Integer myInteger){
this.myInteger = myInteger;
}
public Integer getInteger(){
return myInteger;
}
public void setString(String myString){
this.myString = myString;
}
public String getString(){
return myString;
}
}public class ChangeClass {
public void changeInt(int Int){
Int = 1;
}
public void changeInteger(Integer integer){
integer = new Integer(1);
}
public void changeString(String string){
string = new String("Change string!");
}
public void changeMyClass(MyClass myClass){
myClass.setInt(1);
myClass.setInteger(new Integer(1));
myClass.setString(new String("Change my string!"));
}
public static void main(String[] args) {
int Int;
Integer integer;
String string;
MyClass myClass = new MyClass();
Int = 0;
integer = new Integer(0);
string = new String("String");
myClass.setInt(0);
myClass.setInteger(new Integer(0));
myClass.setString(new String("My string"));
ChangeClass changeClass = new ChangeClass();
changeClass.changeInt(Int);
changeClass.changeInteger(integer);
changeClass.changeString(string);
changeClass.changeMyClass(myClass);
System.out.println(Int);
System.out.println(integer);
System.out.println(string);
System.out.println(myClass.getInt());
System.out.println(myClass.getInteger());
System.out.println(myClass.getString());
}
}
楼主【redbridge】截止到2008-07-19 16:00:36的历史汇总数据(不包括此帖):
发帖的总数量:21 发帖的总分数:460 每贴平均分数:21
回帖的总数量:31 得分贴总数量:6 回帖的得分率:19%
结贴的总数量:21 结贴的总分数:460
无满意结贴数:5 无满意结贴分:210
未结的帖子数:0 未结的总分数:0
结贴的百分比:100.00% 结分的百分比:100.00%
无满意结贴率:23.81 % 无满意结分率:45.65 %
敬礼!
0
String
1
1
Change my string!
其实不需要5分钟。
myClass.setInt(1);
myClass.setInteger(new Integer(1));
myClass.setString(new String("Change my string!"));
}
只有上面的方法有用其实就是检验java值传递在传对象reference的值的时候的情况。
那你们有没有想过:MyClass和Integer都是类(只不过Integer是Java的工具类,直接看不到源代码),为什么在进行参数传递的时候Integer类的内部属性(即Integer.intvalue())没有被改变?
integer = new Integer(1);
}
内部通过new的方法不可能对外边的对象造成影响。
如果需要对外部对象起作用,需要通过调用其方法来实现
对于Integer这种内部数据为final的肯定也不可能通过其他方法改变关键:
Java所有参数都是值传递。
既然“关键: Java所有参数都是值传递。”
当执行这句时:changeClass.changeMyClass(myClass);
无论changeMyClass方法在内部执行了什么语句,myClass的属性值应该是不受影响的。
也就是说在该方法执行之后,System.out.println(myClass.getInt()); 输出应该为0.
但结果变成了1.也就是说,通过参数传递,changeMyClass方法改变了源参数myClass自身的属性(或者说行为)。
其实我也知道传递的是引用(即两个引用指向同一个对象,或者说两个指针指向同一块内存区域)。
但是“关键: Java所有参数都是值传递。”这句话就很难理解了。因为“值传递”给人的理解一般是对象自身的行为是不会因为通过参数传递而改变的。
说的再彻底一点,姑且我们允许Java能够进行引用传递(或者叫地址传递,俗点的说就是能够改变真正源参数自身行文的一种传递方式)。那么请以上面所举的例子为引申,用实例说说“值传递”和“引用传递”(或者叫地址传递)的真正区别是什么?
MyClass myClass = new MyClass();
在堆上创建一个对象,myClass这个变量存在栈上,保存的是对新建立的对象的引用或者叫做句柄。
changeClass.changeMyClass(myClass); //这里 myClass作为参数传递进去,我们分析方法ChangeMyClass()public void changeMyClass(MyClass myClass){
myClass.setInt(1);
myClass.setInteger(new Integer(1));
myClass.setString(new String("Change my string!"));
} 注意参数得到的myClass和changeClass.changeMyClass(myClass); 这里面的myClass不是一个东西,它是复制了一份传递进去的,也就是说方法里的myClass和你调用的时候的myClass不是一个东西,只是把它的值复制了一份传递进去,所以我们称为pass by value.但是这个值和外面的myClass引用到的是同一个对象。
所以你myClass.setInt(1);是对外面保存在堆里的对象的数据进行了修改,当然起作用了。你比较一下其他的方法
integer = new Integer(1); //你把里面的integer引用了新的对象,跟外面的对象有关系吗?
所以还是看上面的方法,你在里面加一句myClass=new MyClass();把方法改变为:
public void changeMyClass(MyClass myClass){
myClass=new MyClass();//这里是把myClass的值改变了,对外面的myClass没有影响,因为这是两个变量。
myClass.setInt(1);
myClass.setInteger(new Integer(1));
myClass.setString(new String("Change my string!"));
} 我想应该是说明白了。
参考《The Java Programming Language》
《Core Java》
对于某些人的理解虽然参数引用改变了源参数自身的行为,但是没有改变它的地址,所以还是“值传递”。
也就是说除非改变了源参数的内存地址才叫真正的引用传递(或者就叫地址传递)?
我还想补充两句:
对于直接用户来说,他们并不关心也无法关心地址的改变(因为java没有指针了)。他们只关心对象自身的属性或者行为是否被改变。因此“值传递”和“引用传递”我觉得应该叫“形参传递”和“实参传递”来定义更加合适。
形参传递(即值传递):不会改变源参数任何自身属性的传递。
实参传递(即引用传递):可能会改变源参数自身属性的传递。
顺便总结一句:不管大家如何讨论值传递和引用传递区别,java肯定不会有参数的地址传递!
因为C++中可以通过&指定应用的方式为引用传递。这时候你完全可以认为引用和引用所指向的对象是同一个东西。但是c++有一个重要的特点是java 不具备的,C++中的引用一旦赋值不能改变。
比如
void changeClass(MyClass &myClass)
{
...
}
内部对myClass的任何修改外面都能知道,但你不能这样myClass=....,语法保证你不能把引用指向新的对象
java做不到,你可以对myClass进行任何的操作,最关键的就是赋值了,比如myClass =new MyClass();这样以来立即切段了和外面的myClass对象所引用的对象的联系,你还认为myClass是个“ 引用”吗?
C++的引用值不能改变这是我知道的,也正是因为C++引用的特性和Java很相似但这点又不太一样。
所以总是以为Java的引用传递就是地址传递。
0
String
1
1
Change my string!