Java传值&传引用

来源:互联网 发布:第三届数据新闻大赛 编辑:程序博客网 时间:2024/06/06 20:58
(一)基本数据类型:传值,方法不会改变实参的值。

public class TestFun {

    public static void testInt(int i){
        i=5;   
    } 

    public static void main(String[] args) {
        int a=0 ;  
        TestFun.testInt(a);
        System.out.println("a="+a);  
    }

}

程序执行结果:a=0 。


(二)对象类型参数:传引用,方法体内改变形参引用,不会改变实参的引用,但有可能改变实参对象的属性值。

举两个例子:

(1)方法体内改变形参引用,但不会改变实参引用 ,实参值不变。

public class TestFun2 {

    public static void testStr(String str){
        str="hello";//型参指向字符串 “hello”   
    } 

    public static void main(String[] args) {
       String s="1" ;  
       TestFun2.testStr(s);
       System.out.println("s="+s); //实参s引用没变,值也不变 
    }
}

执行结果打印:s=1

(2)方法体内,通过引用改变了实际参数对象的内容,注意是“内容”,引用还是不变的。

import java.util.HashMap;
import java.util.Map;

public class TestFun3 {

    public static void testMap(Map map){
        map.put("key2","value2");//通过引用,改变了实参的内容  
    } 

    public static void main(String[] args) {
        Map map = new HashMap(); 
        map.put("key1", "value1");
        new TestFun3().testMap(map);
        System.out.println("map size:"+map.size()); //map内容变化了 
    }
}

执行结果,打印:map size:2 。可见在方法testMap()内改变了实参的内容。

(3)第二个例子是拿map举例的,还有经常涉及的是 StringBuffer :

public class TestFun4 {

    public static void testStringBuffer(StringBuffer sb){
        sb.append("java");//改变了实参的内容 
    } 

    public static void main(String[] args) {
        StringBuffer sb= new StringBuffer("my "); 
        new TestFun4().testStringBuffer(sb);
        System.out.println("sb="+sb.toString());//内容变化了 
    }
}

执行结果,打印:sb=my java 。

所以比较参数是String和StringBuffer 的两个例子就会理解什么是“改变实参对象内容”了。

总结

第一:java方法基本数据类型是传值,对象类型传引用,这是千真万确的。

第二:当参数是对象时,无论方法体内进行了何种操作,都不会改变实参对象的引用。

第三:当参数是对象时,只有在方法内部改变了对象的内容时,才会改变实参对象内容。

 

=================》我是分割线,个人感觉下面这段废话太多,可以选择看不看《===================


    java程序的函数调用到底是传值呢还是传参呢?这可是个难缠的问题,如果搞不清楚还是挺容易出错的。对于这个问题,最经典的解释莫过于“java函数是传值的,java函数传递的参数是对象的引用” 。
    程序和程序中需要用到的对象放在两个相对独立的区域中,那么程序怎么使用对象呢?答案是程序中真正使用对象的地方其实只是声明了一个对象的引用,也就是把堆中分配了的相应对象的地址放到引用中,栈和堆之间就是通过一个一个的引用来联系的。好了,这下清楚了,不管是基本类型变量(int,float,double什么的)还是对象,相应的内存地址中存放的都是一个数(无符号整数,整数,浮点数等)。传递参数的时候传递的就是相应内存地址中的数,所以说“java函数是传值的”。
    当然,这个数对于基本类型和对象类型来说意义是不一样的,对于基本类型这个数就是其值本身,传递值的结果就是,改变新的变量的值不影响旧的变量的值;而对于对象来说这个数是它的地址,传递这个值就相当于传递了真实对象的引用,传递了引用或者说是地址的结果就是变化会全局可见,所以又可以说“java函数传递的参数是对象的引用”。
public class TestRef 
{
 public static void main(String[] args)
 {
  ValueObject vo1 = new ValueObject("A", 1);
  System.out.println("after vo1: " + vo1.getName()); //=A
  
  changeValue1(vo1);
  System.out.println("after changeValue1: " + vo1.getName());
                //=A1, changed
  
  changeValue2(vo1);
  System.out.println("after changeValue2: " + vo1.getName()); 
                //=A1, changeValue2内部的赋值不会影响这里。
 }
 /**
  * 使用vo1自身的函数对其内部数据进行改变是有效的,函数外可反映出来,  * 因为这是对对象本身的操作
  * 这种object称为可变的(mutable)
  * @param vo1
  */
 private static void changeValue1(ValueObject vo1) 
 {
  vo1.setName("A1");
 }
 /**
  * 在函数内给vo1重新赋值不会改变函数外的原始值,因为这种改变了引用的指向
  * @param vo1
  */
 private static void changeValue2(ValueObject vo1) 
 {
  vo1 = new ValueObject("B", 2);
  System.out.println("inside changeValue2: "+ vo1.getName());
                //=B,赋值操作引起的结果变化仅在changeValue2内部有效
 }
}
class ValueObject 
{
 
 public ValueObject() {}
 
 public ValueObject(String name, int id)
 {
  this.name = name;
  this.id = id;
 }
 
 private String name;
 private int id;
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
}
    java中对象的每个实例(就是对象)内存地址是唯一的,它一旦被创建,能够对这个地址进行操作的就是其本身,如果ValueObject类中没有public void setName之类的方法对这个类的实例中的数据进行修改的话,程序是没有任何别的方法可以修改ValueObject类的实例中的数据,这个就是java的封装特性。对于不提供修改内部数据的方法的类,我们称为不可变(immutable)的类。在函数中对传入的参数变量进行赋值操作,只能在函数范围内改变局部变量指向的引用地址,但是不会改变原始地址的内容。因此,在changeValue2(...)函数内部的vo1和函数外的vo1虽然名字相同,但是实际上是不同的实例变量,只不过指向了和函数外的vo1同样的地址,所以当我们用vo1=... 对其进行赋值的时候,只不过是把函数内的临时变量指向了新的地址,并没有改变原始vo1内存地址中的内容。这就是在运行changeValue2(...)之后,vo1的值在main范围内仍然没有被修改的原因。而changeValue1里面是调用的ValueObject本身的function来更改其内容,因此是原始内存地址中的数据被更改了,所以是全局有效的.总结:
对于引用类型的传参也是传值的,传的是引用类型的值,其实就是对象的地址。 
1. java参数传递值的。 
2. java所有对像变量都是对像的引用。
转载自:http://hi.baidu.com/cpuramdisk/item/84a75b5e78007013da163535
原创粉丝点击