java高手们请进(50分)

  • 主题发起人 横刀向天笑
  • 开始时间

横刀向天笑

Unregistered / Unconfirmed
GUEST, unregistred user!
在java中怎样才能实现普通数据类型参数按引用传递给函数,然后进行交换?我试了下列两种方法都不行。
难道java中的普通数据类型只能按值传递吗(而对象类型参数的却可以按引用传递,如数组)?
而在C#中只要加上ref关键字,就可以实现参数按引用传递。
请各位java高手指点迷津!
class SwapTest
{
public void swap(Integer a,Integer b)
{
Integer temp=a;
a=b;
b=temp;
}
public static void main(String[] args)
{
Integer x=new Integer(10);
Integer y=new Integer(26);
System.out.println("x="+x+"/t"+"y="+y);
SwapTest s=new SwapTest();
s.swap(x,y);
System.out.println("x="+x+"/t"+"y="+y);
}

}

class SwapTest
{
public void swap(int a,int b)
{
int temp=a;
a=b;
b=temp;
}
public static void main(String[] args)
{
int x=10,y=26;
System.out.println("x="+x+"/t"+"y="+y);
SwapTest s=new SwapTest();
s.swap(x,y);
System.out.println("x="+x+"/t"+"y="+y);
}

}
结果x、y值还是原来的值。
 
参阅Integer类的说明.
 
是不是要这样,我很长时间不搞Java 了
public void swap(Integer @a,Integer @b)
 
以前学C时,记得有按值传递、按引用传递。
JAVA中相应的概念好像是pass by value,pass handles,以下就是按第二种方法的代码:
class SwapTest
{
public Integer x,y;
public void swap(SwapTest s)
{
Integer temp=s.x;
s.x=s.y;
s.y=temp;
}
public static void main(String[] args)
{
SwapTest s=new SwapTest();
s.x=new Integer(10);
s.y=new Integer(26);
System.out.println("x="+s.x+"/t"+"y="+s.y);
s.swap(s);
System.out.println("x="+s.x+"/t"+"y="+s.y);
}
}
 
你需要研读java关于局部变量和实例变量部分的说明。
你的代码中使用的都是局部变量。楼上的用了实例变量。
 
说一下我的理解:
对于java来说,传参数有2种情况
1.参数为基本数据类型,比如int。 该方式参数是pass by value传递。
所以 swap(int a,int b)调用无效。
2.参数为类的实例对象,比如Integer。 该方式参数是pass by reference传递。
被调用的方法可以得到一个 local reference 的copy。
如果不是很深究的话,也可以把pass by reference
方式类比成其他语言中的指针传递。

得到local reference后,可以通过local reference 对其所指向
的object instance所做的操作,即便方法调用结束后只要object存在,
那操作的效果也就存在。

我们在swap(Integer a,Integer b)末尾加一句。
System.out.println("x="+a+"/t"+"y="+b);
那程序运行的结果将是:
G:/Others>java -cp . SwapTest
x=10 y=26 <--调用s.swap前
x=26 y=10 <--s.swap内部
x=10 y=26 <--调用s.swap后
可以见在swap方法中,确实起了些变化,但却无法影响Swap方法以外的环境。
这是为什么呢?

如果我们把pass by reference当做传递指针。我们对一个指针,
既可以对指针量本身进行操作,也可以对指针所指向的对象进行操作。如果
对指针量本身进行操作,那一出该方法,该local的指针量也就被释放了,
对外界没有影响。java的pass by reference也是同理。
Integer temp=a;
a=b;
b=temp;
该三条语句,其实只是调换了local reference的指向对象,并没有对原来
所指向的对象做任何操作。所以也是不会有效果的。

而kehua的public void swap(SwapTest s)
改变的是所指向对象的状态,所以是有效果的。
具体的可以参见一下:
《Thinking in java》 2nd
附录A 对象的传递和返回
 
如果你的数据总是在一起出没的话
为什么不生成一个类来管理这些数据呢
《refactoring》
 
参数是传值还是传址一直是一个经常被争辩的话题。误解的中心是以下两个事实:
1.对象是传引用的
2.参数是传值的
这两个能够同时成立吗?一个字:是!在java中,你从来没有传递对象,你传递的仅仅是对象的引用!一句话,java是传引用的。然而,当你传递一个参数,那么只有一种参数传递机制:传值!
通常,当程序员讨论传值和传引用时,他们是指语言的参数传递机制,c++同时支持这两种机制,因此,以前使用过c++的程序员开始好像不能确定的java是如何传参数的。java语言为了事情变得简单只支持参数传值的机制。
java中的变量有两种类型:引用类型和原始类型。当他们被作为参数传递给方法时,他们都是传值的。这是一个非常重要的差别,下面的代码范例将说明这一点。在继续前,我们有必要定义一下传值和传引用。
传值意味着当参数被传递给一个方法或者函数时,方法或者函数接收到的是原始值的副本。因此,如果方法或者函数修改了参数,受影响的只是副本,原始值保持不变。
关于java中的参数传递的混乱是因为很多java程序员是从c++转变过来的。c++有引用和非引用类型的变量,并且分别是通过传引用和传值得。java语言有原始类型和对象引用,那么,按照逻辑,java对于原始类型使用传值而对引用是传引用的,就像c++一样。毕竟,你会想到如果你正在传递一个引用,那么它一定是传引用的。这是一个很诱惑人的想法,但是是错误的!
在c++和java中,当函数的参数不是引用时,你传递的是值得副本(传值)。但是对于引用类型就不同了。在c++中,当参数是引用类型,你传递的是引用或者内存地址(传引用),而在java中,传递一个引用类型的参数的结果只是传递引用的副本(传值)而非引用自身。
这是一个非常重要的区别!java不考虑参数的类型,一律传递参数的副本。
 
其实,我觉得就是按照c++的概念来理解java中的引用传递也无不可,因为在java中你不可能
自己去修改引用,而按照楼上的说法,反而容易让人误解.其实java传递的是不是参数的副本
并不重要,因为实际上它所体现的效果就是按引用传递的.它传递的副本只是引用的副本,而
不是引用所指向的内容的副本(对于这一点传递副本一说,我还没有查到相关资料的说法,我
暂且相信楼上的说法是正确的).
最后补充一点,事实上,在java规范中一直在讨论需要引入pass by value的机制,事实上,这里
它已经体现出对现有参数传递方式的一种定性,即按引用传递.这是我个人的理解.
 
顶部