JAVA传值与传引用

在进入正题之前,我们首先来了解一下JAVA对象的引用和实体。在JAVA中对象是在堆中分配内存,对象的引用是在栈中分配内存。也就是说,当用类创建一个对象时,类中的成员变量在堆中分配内存空间,这些内存空间称为该对象的实体和对象的变量。而对象中存放着引用,该引用在栈中分配内存,以确保实体由该对象操作使用。

下面给出一个小例子。

我们定义了一个类的构造方法Point(int x,int y)创建了两个对象p1,p2。Point p1 = new Point(12,16);

Point p2 = new Point(6,18);那么内存模型是:

假如在程序中使用如下的赋值语句:

p1 = p2;

即把p2的引用(p2在内存中的名字)赋值给了p1,因此p1和p2在本质上是一样的.虽然在源程序中p1和p2是两个名字,,但他们在系统中只有一个--0XDD。系统将取消原来分配给p1的内存。这时候p1和p2将具有相同内存实体。则内存模型是:

一个类创建的两个对象,如果具有相同的引用,那么就具有完全相同内存实体。


接下来我们进入正题,在JAVA中当方法被调用,如果方法有参数,那么参数必须实例化,即参数变量必须有具体的值。在JAVA中所有的参数都是“传值”的(请注意这里是引号),也就是说,方法中参数变量的值就是调用者指定值的一个副本。

1.简单类型是按值传递的:

public class Test {  
    public static void test(boolean test) {  
        test = ! test;  
        System.out.println("In test(boolean): test = " + test);  
    }  
    public static void main(String[] args) {  
        boolean test = true;  
        System.out.println("Beforetest(boolean) : test = " + test);  
        test(test);  
        System.out.println("Aftertest(boolean) : test = " + test);  
    }  
}  

运行结果:
Beforetest(boolean) : test = true  
In test(boolean) : test = false  
After test(boolean) : test = true

2.所谓的“传引用”调用:

那么JAVA是传引用还是传值调用,问题还是看你是怎样传递对象。因为JAVA的简单类型没有引用。

那么引用是什么?引用其实是一个对象的名字或者别名。一个对象会在内存中申请一块空间来保存数据。我们访问对象的数据时,不会直接去访问,而是通过引用来访问。引用是一种数据类型,相当于c++中的指针。指示了对象中数据在内存中的地址。


如果我们定义了不只一个引用。这些引用是互不相同的,因为引用也是一种数据类型,但他们的值是相同的,因为都指向了同一块内存地址。


下面来介绍一个例子:

/*例 2 */  
/** 
 * @(#) Test.java 
 * @author fancy 
 */  
public class Test {  
    public static void test(StringBuffer str) {  
        str.append(", World!");  
    }  
    public static void main(String[] args) {  
        StringBuffer string = newStringBuffer("Hello");  
        test(string);  
        System.out.println(string);  
    }  
}  


运行结果:

Hello,World

这里需要纠正一下,看了上面例子不要认为传对象都是引用调用,这道例题中是由于a和b指向了同一块内存地址,所以修改其中一个就可以更改数据。你可以看看下面例子:

/*例 3 */  
/** 
 * @(#) Test.java 
 * @author fancy 
 */  
public class Test {  
    public static void test(String str) {  
        str = "World";  
    }  
    public static void main(String[] args) {  
        String string = "Hello";  
        test(string);  
        System.out.println(string);  
    }  
}  

结果是:

Hello  

看完上面的例子,你可能有点糊涂,为什么这道题就不行了,首先我们来分析一下。当我们把值传进函数还未执行函数体时,这时候string,str都指向了"hello",可是执行完函数体时,str就指向了"world",所以你这时在输出string时就只能看到"hello"。


我们现在可以做出总结了,JAVA中基本数据不存在引用,JAVA的引用类型包括前面学到的对象,数组,以及接口。

具体是否传进函数时是否修改了值,还是要看你是否直接对值进行了修改,还是把引用改变了指向的对象。


最后,之所以存在这个问题,主要是由于c语言中有个东西叫“指针”。JAVA中没有指针

我们给出两个例子以示区分:

/** 
 * @(#) test.c 
 * @author fancy 
 */  
void SwapValue(int a, int b) {  
    int t = a;  
    a = b;  
    b = t;  
}  
void SwapPointer(int * a, int * b) {  
    int t = * a;  
    * a = * b;  
    * b = t;  
}  
void main() {  
    int a = 0, b = 1;  
    printf("1 : a = %d, b = %d/n", a, b);  
    SwapValue(a, b);  
    printf("2 : a = %d, b = %d/n", a, b);  
    SwapPointer(&a, &b);  
    printf("3 : a = %d, b = %d/n", a, b);  
}  

结果是:

1: a = 0, b = 1  
2 : a = 0, b = 1  
3 : a = 1, b = 0  

另外一个:

/** 
 * @(#) Test.java 
 * @author fancy 
 */  
public class Test {  
    public static void swap(int[] data, int a, int b) {  
        int t = data[a];  
        data[a] = data[b];  
        data[b] = t;  
    }  
    public static void main(String[] args) {  
        int[] data = new int[10];  
        for (int i = 0; i < 10; i++) {  
            data[i] =(int) (Math.random() * 100);  
           System.out.print(" " + data[i]);  
        }  
        System.out.println();  
        for (int i = 0; i < 9; i++) {  
            for (int j =i; j < 10; j++) {  
               if (data[i] > data[j]) {  
                   swap(data, i, j);  
               }  
            }  
        }  
        for (int i = 0; i < 10; i++) {  
           System.out.print(" " + data[i]);  
        }  
        System.out.println();  
    }  
}  

结果是:

7869 94 38 95 31 50 97 84 1  
1 31 38 50 69 78 84 94 95 97 

最后感谢houpuhope的博客的例子。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值