java只有值传递

在Java编程语言中,只有值传递,没有引用传递


首先,要明白什么是值传递,什么是引用传递。

①值传递的定义

就是传递变量的值。

②引用传递的定义

就是传递变量的地址。


现在,举例举例解释下值传递和引用传递,这里先用C++的语言对这两个概念进行解释,因为C++的世界中既有值传递,也有引用传递,而Java的世界里,只有值传递。

C++ 值传递的示例:

int main(void) //主函数
{
int a = 1 ;
int b = 2 ;
cout << "a = " << a << ", " << "b = " << b << endl ;//打印出调用Swap函数前a和b的值,a=1,b=2
Swap(a, b) ;
cout << "a = " << a << ", " << "b = " << b << endl ;//打印出调用Swap函数后a和b的值,a=1,b=2
system("pause") ;
return 0 ;
}

void Swap(int x, int y) //被调用的函数
{
int temp = x ;
x = y ;
y = temp ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

正如前面定义所说的那样,在调用Swap函数之前a=1,b=2,当调用Swap函数时,实参a把值的副本传给形参x,实参b也把值的副本传给形参y,之后就没有a和b什么事了。Swap函数里面的操作,实际上都是对x和y的操作。
具体如下图所示,在调用Swap函数之前,实参a的值是1,实参b的值是2,形参x和形参y里面没有放任何值。
这里写图片描述
当调用Swap函数时,实参a把自身的值拷贝一份,然后把拷贝的副本传递给形参x,实参b同理。
这里写图片描述
紧接着,进入Swap函数,int temp = x;就是再创建一个局部变量temp,把变量x的值赋值给变量temp。
这里写图片描述
然后把变量y的值赋值给变量x。
这里写图片描述
最后再把变量temp的值赋值给变量x。
这里写图片描述
图例的结果和程序打印出来的结果一样,a=1,b=2。整个过程就是值传递的具体实现,通过值传递,实参把自身的值拷贝出一个副本,然后把这个副本传递给形参,而被调函数的操作都是针对形参的,实参不会有任何影响。

C++ 引用传递的示例:

int main(void) //主函数
{
int a = 1 ;
int b = 2 ;
cout << "a = " << a << ", " << "b = " << b << endl ;//打印出调用Swap函数前a和b的值,a=1,b=2
Swap(a, b) ;
cout << "a = " << a << ", " << "b = " << b << endl ;//打印出调用Swap函数后a和b的值,a=2,b=1
system("pause") ;
return 0 ;
}

void Swap(int &x, int &y) //被调用的函数
{
int temp = x ;
x = y ;
y = temp ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

引用传递,也如前面的定义所说的那样,传递的是变量的地址。在调用Swap函数之前,实参a的值是1,地址为0x00000001,实参b的值是2,地址为0x00000002,形参x和形参y里面没有放任何值。
这里写图片描述
当调用Swap函数时,实参a把自身的地址传给形参x,实参b同理。注意,&是C++中的取地址运算符,表示取得变量的地址。
这里写图片描述
紧接着,进入Swap函数,int temp = x;就是再创建一个局部变量temp,把x的值赋值给temp,由于这是引用传递,被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量,所以,通过形参x存放的地址,找到实参a的值,把值赋值给变量temp。
这里写图片描述
同理,把变量y的值赋值给变量x。
这里写图片描述
最后再把变量temp的值赋值给变量x。
这里写图片描述
图例的结果和程序打印出来的结果一样,a=2,b=1。整个过程就是引用传递的具体实现,通过引用传递,实参把自身的地址传递给形参,然后被调函数的操作通过形参中的地址,间接对实参进行操作。


以上部分就是对值传递和引用传递的理解。

而在Java的世界里,就只有值传递。

对于基本类型的值传递,代码如下,具体实现跟C++类似。

    public static void main(String[] args){
        int a = 1,b = 2;
        System.out.println("a="+a+" , b="+b);
        swap(a,b);
        System.out.println("a="+a+" , b="+b);
    }

    public static void swap(int x,int y){
        int temp = x;
        x = y;
        y = temp;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
//控制台输出的结果
    a=1 , b=2
    a=1 , b=2
  • 1
  • 2
  • 3

对于对象的值传递,代码如下。

//Person类
    public class Person {
        private String name;
        private int age;
        public Person(String name,int age){
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public String toString(){
            return this.name+":"+this.age;
        }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
//测试
public class test { 
    public static void main(String[] args){
         Person person = new Person("cjt",23);
         System.out.println(person);
         modify(person);
         System.out.println(person);
    }

    public static void modify(Person p){
        p.setName("chenjiatao");
        p.setAge(18);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
//控制台输出的结果
cjt:23
chenjiatao:18
  • 1
  • 2
  • 3

看到对象值传递的结果,可能会让你想到前面C++说的引导传递,会发出疑问:不是值传递吗?怎么结果变了,这应该是引用传递吧?在这里,我这声明一次,在Java的世界里,只有值传递!
对于对象的值传递,具体看下面的解释:
这里写图片描述
上面的这张图示中展现的是Person person = new Person(“cjt”,23)这行代码具体过程,我们可以知道,我们创建了一个person对象,里面的属性是name为cjt,age为23,对象的堆上的地址是0x00000001。并且,声明实参变量person,把person对象的引用赋值给变量person,所以,如图所示,实参person里面存放的值,是指向实际person对象的引用。
这里写图片描述
紧接着,调用modify方法,实参person把自身的值拷贝一份,然后把拷贝的副本传递给形参p,此时,形参p的值也是0x00000001。注意,这里完全和前面C++部分讲的值传递一模一样,实参p把自身的副本传递给形参p之后,就没实参p什么事了,modify函数内部执行的任何代码,都不会影响到实参person里面的值,即实参person里面一直存放的0x00000001。然后执行modify函数内部的方法,由于形参p的值是同实参person一样,也是指向person对象的引用,所以modify函数内部执行的代码,改变了person对象里面的属性。当然,有的人可能会说,这个也有点类似之前C++部分讲的引用传递呀。这里要注意了,我们的关注点是实参到形参的传递过程,而且,如果说这个对象的传递过程是引用传递的话,那实参person传递给形参p的值,应该是实参person这个变量的地址,而不是person对象的地址,再说,在Java的世界里,并没有C++那样的取地址运算符&,你见到过有人在Java中用过&person这样的表达式吗?所以,正如程序所运行的结果那样,person对象的里面的属性变成了name:chenjiatao,age:18。

猜你喜欢

转载自blog.csdn.net/csw19970124/article/details/80802497