Java中没有引用传递只有值传递(在函数中)

Posted 请叫我大表哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java中没有引用传递只有值传递(在函数中)相关的知识,希望对你有一定的参考价值。

◆传参的问题

  引用类型(在函数调用中)的传参问题,是一个相当扯的问题。有些书上说是传值,有些书上说是传引用。搞得Java程序员都快成神经分裂了。所以,我们最后来谈一下“引用类型参数传递”的问题。

  如下例子,假设现在要把刚才创建的那一坨字符串打印出来,我们会使用如下语句:

StringBuffer str = new StringBuffer();
System.out.println(str); //这个语句又是什么意思捏?这时候就两说了。

  第一种理解:可以认为传进函数的是str这个指针,指针说白了就是一个地址的值,说得再白一点,就是个整数。按照这种理解,就是传值的方式。也就是说,参数传递的是指针本身,所以是传值的。

  第二种理解:可以认为传进去的是StringBuffer对象,按照这种理解,就是传引用方式了。因为我们确实是把对象的地址(也就是引用)给传了进去。

  费了这么多口水,其实不论是传引用还是传值,都可以讲得通,关键取决于你是如何看待参数所传递的东西。这就好比量子力学中“光的波粒二象性”,如果你以粒子的方式去测量它,它看起来像粒子;如果你以波动的方式去观测它,它看起来像波动。

/**
 * @description Java中没有引用传递只有值传递
 *
 * @author Alexia
 * @date 2013-10-16
 *
 */
class Person {
 
    private String name;

    private String sex;
 
    public Person(String x, String y) {
        this.name = x;
        this.sex = y;
    }
 
    // 重写toString()方法,方便输出
    public String toString() {
        return name + " " + sex;
    }
 
    // 交换对象引用,这里的p1和p2是swapObject这个函数的变量(局部变量),
    // p1、p2接收的就是传递进来的一个堆内存的地址,改变p1、p2的指向只是改变了这两个局部变量的指向。
    // 实际的全局变量还是没变的
    public static void swapObject(Person p1, Person p2) {
        Person tmp = p1;
        p1 = p2;
        p2 = tmp;
    }
 
    // 交换基本类型
    public static void swapInt(int a, int b) {
        int tmp = a;
        a = b;
        b = tmp;
    }
 
    // 交换对象数组
    public static void swapObjectArray(Person[] p1, Person[] p2) {
        Person[] tmp = p1;
        p1 = p2;
        p2 = tmp;
    }
 
    // 交换基本类型数组
    public static void swapIntArray(int[] x, int[] y) {
        int[] tmp = x;
        x = y;
        y = tmp;
    }
 
    // 改变对象数组中的内容
    public static void changeObjectArray(Person[] p1, Person[] p2) {
        Person tmp = p1[1];
        p1[1] = p2[1];
        p2[1] = tmp;
        // 再将p1[1]修改
        Person p = new Person("wjl", "male");
        p1[1] = p;
    }
 
    // 改变基本类型数组中的内容
    public static void changeIntArray(int[] x, int[] y) {
        int tmp = x[1];
        x[1] = y[1];
        y[1] = tmp;
        x[1] = 5;
    }
}
 
public class ByValueTest {
 
    public static void main(String[] args) {
 
        // 建立并构造两个对象
        Person p1 = new Person("Alexia", "female");
        Person p2 = new Person("Edward", "male");
 
        System.out.println("对象交换前:p1 = " + p1.toString()); //Alexia female
        System.out.println("对象交换前:p2 = " + p2.toString()); //Edward male
 
        // 交换p1对象和p2对象
        Person.swapObject(p1, p2);
        // 从交换结果中看出,实际对象并未交换
        System.out.println("对象交换后:p1 = " + p1.toString()); //Alexia female
        System.out.println("对象交换后:p2 = " + p2.toString()); //Edward male
 
        // 建立两个对象数组
        Person[] arraya = new Person[2];
        Person[] arrayb = new Person[2];
 
        // 分别构造数组对象
        arraya[0] = new Person("Alexia", "female");
        arraya[1] = new Person("Edward", "male");
        arrayb[0] = new Person("jmwang", "female");
        arrayb[1] = new Person("hwu", "male");
 
        System.out.println("对象数组交换前:arraya[0] = " + arraya[0].toString() + ", arraya[1] = " 
        + arraya[1].toString()); //Alexia female,Edward male System.out.println("对象数组交换前:arrayb[0] = " + arrayb[0].toString() + ", arrayb[1] = "
        + arrayb[1].toString()); //jmwang female,hwu male // 交换这两个对象数组 Person.swapObjectArray(arraya, arrayb); System.out.println("对象数组交换后:arraya[0] = " + arraya[0].toString() + ", arraya[1] = "
        + arraya[1].toString()); //Alexia female,Edward male System.out.println("对象数组交换后:arrayb[0] = " + arrayb[0].toString() + ", arrayb[1] = "
        + arrayb[1].toString()); //jmwang female,hwu male // 建立两个普通数组 int[] a = new int[2]; int[] b = new int[2]; // 给数组个元素赋值 for (int i = 0; i < a.length; i++) { a[i] = i; b[i] = i + 1; } System.out.println("基本类型数组交换前:a[0] = " + a[0] + ", a[1] = " + a[1]); //0,1 System.out.println("基本类型数组交换前:b[0] = " + b[0] + ", b[1] = " + b[1]); //1,2 // 交换两个基本类型数组 Person.swapIntArray(a, b); System.out.println("基本类型数组交换后:a[0] = " + a[0] + ", a[1] = " + a[1]); //0,1 System.out.println("基本类型数组交换后:b[0] = " + b[0] + ", b[1] = " + b[1]); //1,2 // 改变对象数组的内容 Person.changeObjectArray(arraya, arrayb); System.out.println("对象数组内容交换并改变后:arraya[0] = " + arraya[0].toString() + ", arraya[1] = "
        + arraya[1].toString()); //Alexia female,wjl male System.out.println("对象数组内容交换并改变后:arrayb[0] = " + arrayb[0].toString() + ", arrayb[1] = "
        + arrayb[1].toString()); //jmwang female,Edward male // 改变基本类型数组的内容 Person.changeIntArray(a, b); System.out.println("基本类型数组内容交换并改变后:a[0] = " + a[0] + ", a[1] = " + a[1]); //0,5 System.out.println("基本类型数组内容交换并改变后:b[0] = " + b[0] + ",b[1] = " + b[1]); //1,1 } }

   说明:不管是对象、基本类型还是对象数组、基本类型数组,在函数中都不能改变其实际地址但能改变其中的内容。

  【相当于传递进来的栈内存的值,栈内存只存放地址和基本数据内容,是不可在函数中改变的】

 

以上是关于Java中没有引用传递只有值传递(在函数中)的主要内容,如果未能解决你的问题,请参考以下文章

为什么大家都说Java中只有值传递?

为什么大家都说Java中只有值传递?

请注意,java中没有引用传递-----转载

为什么Java只有值传递?

弄懂Java为何只有值传递

java方法参数传递方式只有----值传递!