日期:2014-05-20  浏览次数:20841 次

java中有无引用传递
讨论下,java中有无引用传递,
为什么很多人说java中没有引用传递呢?

------解决方案--------------------
我个人理解翻来覆去就两句话:
1、Java函数调用时,参数传递方式为值传递;
2、当该参数类型为对象(Object)时,则所传递的值为对象的引用(也可理解为地址)。


如果你认为Java函数调用有指针传递或引用传递的话,你可以尝试编写这样一个函数来验证:
public void swap(Object a, Object b);
效果就是调用后,主调函数的这两个对象互换即可。

比如主调函数是:
String a = "A";
String b = "B";
swap(a, b);
System.out.println(a); // 这里请输出 B
System.out.println(b); // 这里请输出 A


当然,你别用反射之类的方式直接去修改常量池啥的招数。。。
------解决方案--------------------
如果传递的是primities : int, double, short etc, 是值传递。
如果传递的是对其他object的引用,就是传递的那个object reference

int cube (int a) {<-- pass by value
 return a*a*a
}

Box enLargbox ( Box aBox){ <-- pass by reference
aBox.setLength (aBox.length * 2);
aBox.setWidth (aBox.width *2);
aBox.setHight (aBox.hight *2);
 return aBox;
}
------解决方案--------------------
其实不能说Java "无引用传递", 而是Java针对非Primitive的数据类型"自动”进行了引用传递。
在C++里,假设有一个对象叫做foo, 那么在传递参数的时候:
C/C++ code

//函数fun
void fun(Foo foo){
      ...
}
//传递参数foo给函数fun
fun(foo);

------解决方案--------------------
你就这样理解:
值传递就是值的拷贝
引用传递就是引用的拷贝
比如
public class Demo{
public void testInt(int i){
 ++i;
}
public void testStrintBuilder(StringBuilder sb){
 sb.append("123");
}
public static void main(String[] args){
 Demo demo = new Demo();
 int i = 1;
 demo.testInt(i);
 StringBuilder sb = new StringBuilder();
 demo.testStrintBuilder(sb);
 //打印1,表示参数拷贝
 System.out.println(i);
 //打印123,表示参数没有拷贝,还是之前的引用
 System.out.println(sb.toString);
}
}

------解决方案--------------------
1、java无引用传递,方法的参数(基础类型)在传进去之后,对参数的操作不会修改原值;
2、对于参数为对象的情况,在传递之前,是复制该对象的引用,在方法内,如果复制的该引用重新赋值了,传参数的那个对象不会被改变;

------解决方案--------------------
这是我以前写的一个测试类,大家看看,不包无错
Java code

import java.util.ArrayList;
import java.util.List;


/**
 * 结论:在JAVA中
 *     赋值或传递基本类型时,是通过复制基本类型的值来实现的;
 *     赋值或传递对象时,是通过传递引用(指针)来实现的。
 */
public class PassParameter {
    
    public int count = 0;
    public String content = "Hello world";
    public PassParameter pp;

    public static void main(String[] args) {
        
        PassParameter p = new PassParameter();
        int i1 = 0;
        int i2 = i1;
        Integer integer = 0;
        String str = "Hello world";
        List<Integer> intListA = new ArrayList<Integer>();
        List<Integer> intListB = new ArrayList<Integer>();
        List<String> strListA = new ArrayList<String>();
        List<String> strListB = strListA;
        
        /////////////////////////////////////////////////////////
        
        // 基本类型是通过复制值传递的
        System.out.println("Before: i = " + i1);
        p.addInt(i1);
        System.out.println("After: i = " + i1);
        
        // 对象是通过传递引用(指针)传递的
        System.out.println("Before: str = " + str);
        p.appendString(str);
        System.out.println("After: str = " + str);
        
        // 对象是通过传递引用(指针)传递的
        System.out.println("Before: Integer = " + integer);
        p.addInteger(integer);
        System.out.println("After: Integer = " + integer);
        
        // 成员变量基本类型与普通基本类型无异
        System.out.println("Before: count = " + p.count);
        p.addInt(p.count);
        System.out.println("After: count = " + p.count);
        
        // 成员String类型变量与普通String类型变量无异
        System.out.println("Before: content = " + p.content);
        p.appendString(p.content);
        System.out.println("After: content = " + p.content);
        
        // 对象是通过传递引用(指针)传递的
        p.pp = new PassParameter();
        System.out.println("Before: Class = " + p.pp.count);
        p.changeClass(p.pp);
        System.out.println("After: Class = " + p.pp.count);
        
        // 容器(对象)是通过传递引用(指针)传递的
        System.out.println("Before: List size = " + intListA.size());
        p.addInteger(intListA);
        System.out.println("After: List size = " + intListA.size());
        intListB = intListA;
        p.addInteger(intListB);
        System.out.println("After2: List size = " + intListA.size());
        
        // 基本类型是通过复制值传递的
        i1 = 10000;
        i2 = i1;
        i1++;
        System.out.println("i1 = " + i1);
        System.out.println("i2 = " + i2);
        
        // 容器(对象)是通过传递引用(指针)传递的
        strListA.add("a");
        strListB.add("b");
        System.out.println("strListA.size = " + strListA.size());
        System.out.println("strListB.size = " + strListB.size());
        
        /////////////////////////////////////////////////////////
    }
    
    public void addInt(int i) {
        i++;
    }
    
    // 由于传递后对象进行重赋值使引用对象(指针)发生了改变,所以对原对象不会有影响
    public void addInteger(Integer i) {
        i = 10;
    }
    
    // 由于传递后对象进行重赋值使引用对象(指针)发生了改变,所以对原对象不会有影响
    public void appendString(String str) {
        str = str + " !";
    }

    public void addInteger(List<Integer> intList) {
        intList.add(1);
        intList.add(2);
        intList.add(3);
        intList.add(4);
        intList.add(5);
    }
    
    public void changeClass(PassParameter pp) {
        pp.count++;
    }
}