Java的值传递和引用传递

行参和实参

行参:方法在被调用的时候需要传递进来的参数。如function(int a)中的参数a,只有在方法被调用的时候a才有意义。
实参:方法在被调用时,实计被传入的值。在方法被调用前已经被初始化。

JAVA中基本类型和引用类型

基本类型:byte、short、int、long、float、double、char、boolean
引用类型:类,数组等

值传递和引用传递

把实参的值赋值给行参,那么对行参的修改不会影响实参的值
把实参的地址传递给行参,行参和实参是同一个对象,只是名字不同,对行参的修改会影响实参的值。

下面我们先来看一看基本类型的操作:

 public static void main(String[] args) {
        int a=1;
        System.out.println("a="+a);
        func(a);
        System.out.println("a="+a);
    }
    private  static void func(int a){
        a=10;
    }

输出结果为:

a=1
a=1

通过上面的结果可以看出,对于基本类型的数据,在实参传入形参时,都是值传递,而不是内容本身。

下面我们来看看引用类型的操作:

   public static void main(String[] args) {
       P p=new P();
       p.setName("芃兮贝贝");
       System.out.println(p.getName());
       func(p);
       System.out.println(p.getName());
    }
    private  static void func(P p){
        p.setName("贝贝");
    }

输出结果为:

芃兮贝贝
贝贝

通过上面的结果可以看出在方法中对引用类型的行参进行修改,最后实参的值也被修改了。那么是不是可以得出结论:

java中基本类型是值传递,引用类型是引用传递呢?

接下来我们再看一个例子:

   public static void main(String[] args) {
       P p=new P();
       p.setName("芃兮贝贝");
       System.out.println(p.getName());
       func(p);
       System.out.println(p.getName());
    }
    private  static void func(P p){
        p=new P();
        p.setName("贝贝");
    }

这段代码比上面的代码是方法func中增加了一行: p=new P(); 我们来看看结果:

芃兮贝贝
芃兮贝贝

奇怪,为什么这次实参的值没被修改呢? 其实,熟悉JVM的朋友们都知道,在JVM中对象是存储在堆内存中的,而且堆内存是共享的,而变量p的值只是一个堆内存的地址,当调用func时,把实参的值传给行参时,是传的一个内存地址,这个时候实参和行参是指向的同一个地址。这个时候如果对行参的修改自然实参也是读到修改后的内容。但是如果行参重新new了一个对象,这个时候JVM会在堆中重新创建内存块来存这个对象。这个时候行参和实参就是两个不同的内存地址了。现在对行参的修改自然是不会影响实参。

因此可见:在Java中所有的参数传递,不管基本类型还是引用类型,都是值传递,或者说是副本传递。

如果是对基本数据类型的数据进行操作,由于原始内容和副本都是存储实际值,并且是在不同的栈区,因此形参的操作,不影响原始内容。

如果是对引用类型的数据进行操作,分两种情况,一种是形参和实参保持指向同一个内存地址,则形参的操作,会影响实参指向的对象的内容。一种是形参被改动指向新的内存地址(如重新赋值引用),则形参的操作,不会影响实参指向的对象的内容。

posted @ 2020-01-17 10:16  芃兮JavaChat  阅读(165)  评论(0编辑  收藏  举报