Java参数传递

Java参数传递

一、java中只存在传值方式的参数传递

java中的参数传递容易引起混淆,尤其是对于那些有过c/c++经历的读者。在c/c++中参数传递既有传值,又有传引用,而在java中只存在传值方式的参数传递。但是由于java中又有引用的概念,这就使得参数传递容易引起初学者的混淆。

因此,java中只存在传值方式的参数传递

二、基本数据类型,对象数据类型参数传递

(1)基本数据类型的参数传递:

将实际参数的值复制一份(值的拷贝),传递给方法的形式参数,形式参数值的改变不会影响所传入的实际参数的值。

(2)对象数据类型的参数传递:

eg:Stringstr=new String(“abc”);

使用传值方式传递参数,将str的值(对象的引用)复制一份传递给对象变量copyStr【即:把对象在内存中的地址拷贝了一份传给了参数copyStr这是计算机的存储区中会同时存在两个独立的对象变量str,copyStr,这两个对象变量均指向字符串对象”abc”。

说明:

就对象而言,不是将对象本身传递给方法,而是将对象的的引用或者说对象的首地址传递给方法,引用本身是按值传递的。

也就是说,将引用的副本传递给方法(副本就是说明对象此时有两个引用了),通过对象的引用,方法可以直接操作该对象

(3)对象数据类型参数传递典型

【1】String对象里面的内容,一旦创建就不会改变,因此属于状态不可转换对象;

【2】StringBuffer,StringBuilder对象,都是转态可转换对象,因为这两个对象里面都有方法(比如:append)可以修改对象里面的内容

【3】对象数组(Object[] a),数组里面的内容可以改变,通过指定对象数组的索引,进行数值的覆盖,即:修改原来数组索引位置的值。

(4)状态可转换对象于状态不可转换对象说明

如果一个对象可以在不改变其在内存中的存储位置的情况下而改变其本身的状态,即是状态可转换对象;否则就是状态不可转换对象。

状态可转换对象:StringBuffer类型的对象中存在append方法来改变对象的状态,所以StringBuffer类型的对象是状态可转换对象

状态不可转换对象:String类型的对象中不存在任何方法来改变对象的状态,要改变String类型的对象的状态必须生成新的String对象,所以String类型的对象是状态不可状态对象

结论:

(1)如果一个方法接收的参数为状态可转换对象,那么该方法可以通过调用该对象中适当的方法(对象本身的方法)来改变实际参数的状态;如果一个方法接收的参数为状态不可转换对象,那么该方法不可改变实际参数的状态。

2)如果对象本身就具有改变自身的数据内容的方法,那么在传递参数过程种,对象里面的内容会发生改变,反之,则不会。

StringBuffer类型的对象中存在append方法来改变对象的状态,所以StringBuffer类型的对象在参数传递时可以改变原来对象里的内容。

三、案例与图解分析

1、基本数据类型的参数传递

(1)实例

package param;
/*
 * 基本数据类型参数传递
*/
public class BasicData {
 
    public static void changeValue(int x){//x为形式参数
       x++;
    }
    public static void main(String[] args) {
       int bonus=100;
       System.out.println("传参数前bonus:"+bonus);//传参数前bonus:100
       BasicData.changeValue(bonus);
       System.out.println("传参数后bonus:"+bonus);//传参数后bonus:100
      
    }
 
}


(2)图解分析

 分析:

结果为什么是不变呢?

执行 int bonus=100后,变量bonus的值为100,详情(见图A.1(a))

当执行语句BasicData.changeValue(bonus);时,由于java使用传值方式传递参数,所以bonus的值将首先复制一份传递给x,这时候计算机的存储区中会同时存在两个独立的变量bonus和x,并且两个变量的值相等(见图A.1(b))。执行changeValue的方法体是,x的值增加了1,由于bonus和x是两个独立的变量,因此x值的正价不会影响到bonus(见图A.1(c))。当方法执行完毕后,x不再有效,但bonus的值没有改变。

2、对象数据类型的参数传递

2.1参数为单个对象

2.1.1参数为String对象的参数传递
2.1.1.1例子一
(1)实例一
package param;
/*
 * 参数为String对象的参数传递
 */
public class StringParam {
 
    public static void changStr(String str){//Str为形式参数
       str=str+"cde";
    }
    public static void main(String[] args) {
       String aStr=new String("abc");
       System.out.println("传参数前aStr的值:"+aStr);//传参数前aStr的值:abc
       StringParam.changStr(aStr);//aStr为实际参数
       System.out.println("传参数后aStr的值:"+aStr);//传参数后aStr的值:abc
 
    }
 
}
(2)图解分析

 分析:

aStr所指对向那个的字符串仍然为”abc”,为什么?

当执行完语句String aStr=new String("abc");是,对象变量aStr指向字符串对象"abc"(见图A.2(a));

执行语句StringParam.changStr(aStr);时,尽管aStr是对象的一个引用,但由于java使用传值方式传递参数,

所以aStr的值(对象的引用)将首先复制一份传递给对象变量str。这时候计算机存储区中会同时存在两个独立的对象变量

aStr和str,这两个对象变量均指向字符串对象"abc"(见图A.2(b))。执行changStr的方法体时,

系统新生成了一个字符串对象"abccde",并赋值给str,这是str将指向对象"abccde"(见图A.2(c))。

由于aStr和str是两个独立的对象变量,str所指对象的改变不会影响到aStr所指的对象,

即:aStr仍旧指向原来的字符串"abc"。当方法执行完毕后,str不再有效,会在适当的时候被回收,但aStr所指对象依旧没有改变

 

2.1.1.2例子二
(1)实例二

package param;
/*
 * 交换两个传入对象的值
 * 交换失败,为什么?
*/
public class BasicDataSwap {
   
    public static void swap(Object a,Object b){
       Object temp=a;
       a=b;
       b=temp;
    }
    public static void main(String[] args) {
   
       String aString="aaa";
       String bString="bbb";
       System.out.println("交换前--aaa值为:"+aString+" bbb值为:"+bString);
       //交换前--aaa值为:aaa bbb值为:bbb
       BasicDataSwap.swap(aString,bString);
       System.out.println("交换后--aaa值为:"+aString+" bbb值为:"+bString);
       //交换后--aaa值为:aaa bbb值为:bbb
    }
}

(2)分析

交换失败,为什么?

分析:

(可以参考String对象赋值失败进行分析,原理一样)

通过对象进行传递,其实传递的是对象的地址值。也就是将(实参)对象aString和bString的值(对象的引用)

进行拷贝一份传给对象变量a和b(形参),形参引用和实参引用指向的是同一个对象,

但是在函数体中,我们所有的操作都只是对形参引用进行赋值运算,

这其中的赋值运算:Objecttemp=a;a=b;b=temp;完毕后,a指向了另外一个对象,b也是指向了另外一个对象,这也就是说:

对应用的赋值运算只会让引用重新指向另一个对象(形参的地址值改变了,已经不是原来的那个地址值,即:指向的是和实参不一样的地址,所以对于不同地址上,它们拥有各自的内存空间,它们相互之间数值的改变是毫无关系的),

因此函数体只是将这些拷贝出来的引用重新指向其它对象,并没有改变这些对象的值,

也没有改变原来的实参引用指向的对象,因此该函数并没有达到交换两个整数的目的。

2.1.2参数为StringBuffer对象的参数传递
(1)实例

package param;
/*
 * 参数为StringBuffer对象的参数传递
 */
public class StringBufferParam {
 
    public static void changeStrBuf(StringBufferstr){
       str.append("cde");
    }
    public static void main(String[] args) {
       StringBuffer aStrBuf=new StringBuffer("abc");
       System.out.println("传参数前aStr的值:"+aStrBuf);//传参数前aStr的值:abc
       StringBufferParam.changeStrBuf(aStrBuf);//aStr为实际参数
       System.out.println("传参数后aStr的值:"+aStrBuf);//传参数后aStr的值:abccde
    }
 
}

(2)图解分析

分析:

aStrBuf所指向的对象变为"abccde",为什么?

当执行完语句StringBufferaStrBuf=new StringBuffer("abc");时,对象变量aStrBuf指向字符串对象"abc"(见图A.3(a));

执行语句StringBufferParam.changeStrBuf(aStrBuf);时,尽管aStr是对象的一个引用,但由于java使用传值方式传递参数,所以aStrBuf的值(对象的引用)将首先复制一份传递给对象变量str。

这时候计算机存储区中会同时存在两个独立的对象变量aStrBuf和str,

这两个对象变量均指向字符串对象"abc"(见图A.3(b))。

执行changeStrBuf的方法体时,方法体中的语句str.append("cde");直接调用str所指对象中的append方法,改变了所指对象的内容为:"abccde"。(见图A.3(c))。【而不是像String对象一样,让str指向了一个新的对象。】

因为对象"abc"的内容改变为"abccde",所以最终str所指的对象内容改变了。(见图A.3(d))

2.2参数为对象数组的参数传递

(1)实例

package param;
/*
 * 参数为对象数组的参数传递
 * 交换成功,为什么?
*/
public class ObjectArrayParam {
    public static void swapArray(Object []array,inti,intj){
       if(i!=j){//将对象数组中位置为i和j的两个数组元素进行交换
           Object temp=array[i];
           array[i]=array[j];
           array[j]=temp;
       }
    }
    public static void main(String[] args) {
       String[] strArray={"tom","jerrey"};
       System.out.println("交换前--strArray[0]="+strArray[0]+" --- strArray[1]="+strArray[1]);
       //交换前--strArray[0]=tom --- strArray[1]=jerrey
      
       ObjectArrayParam.swapArray(strArray, 0, 1);
      
       System.out.println("交换后--strArray[0]="+strArray[0]+" --- strArray[1]="+strArray[1]);
       //交换后--strArray[0]=jerrey ---strArray[1]=tom
 
    }
 
}

(2)图解分析

 交换成功,为什么?

 分析:

初始时,strArray的存储情况如图A.4(a)所示。随后,strArray的值复制一份传递给形式参数array(见图A.4(b))。

swapArray方法中的三条语句

Object temp=array[i];array[i]=array[j];array[j]=temp;

依次执行的结果如图A.4(c)所示。

swapArray方法返回后,a和temp都不再有效,因此最终的结果如图A.4(d)所示。

实质原因:对象数组里面的元素可以改变!

 

四、参考文章

1、csdn博客参考文章1

文章:Java函数的传参机制——你真的了解吗?

网址:http://blog.csdn.net/whuxinxie/article/details/54895768

2、csdn博客参考文章2

文章:java 传递参数的两种方式

网址:http://blog.csdn.net/maoyeqiu/article/details/49250339

3、csdn博客参考文章3

文章:Java中方法调用参数传递的方式是传值,尽管传的是引用的值而不是对象的值。(Does Java pass by reference or pass byvalue?)

网址:http://blog.csdn.net/jubincn/article/details/7221969

4、csdn博客参考文章4

文章:Java值传递以及引用的传递、数组的传递!!

网址:http://blog.csdn.net/niuniu20008/article/details/2953785

5、Java书籍

书名:Java程序设计与应用开发(第2版)  清华大学出版社

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值