(一)基本数据类型:传值,方法不会改变实参的值。


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所有对像变量都是对像的引用。