JAVA⽅法中参数到底是值传递还是引⽤传递
当⼀个对象被当作参数传递到⼀个⽅法后,在此⽅法内可以改变这个对象的属性,那么这⾥到底是值传递还是引⽤传递?
答:是值传递。Java 语⾔的参数传递只有值传递。当⼀个实例对象作为参数被传递到⽅法中时,参数的值就是该对象的引⽤的⼀个副本。指向同⼀个对象,对象的内容可以在被调⽤的⽅法内改变,但对象的引⽤(不是引⽤的副本) 是永远不会改变的。
Java的参数传递,不管是基本数据类型还是引⽤类型的参数,都是按值传递,没有按引⽤传递!
对于参数的传递可以分为两种情况:
1.基本数据类型的参数
1 public class TransferTest {
2    public static void main(String[] args) {
3        int num = 1;
4        System.out.println("changeNum()⽅法调⽤之前:num = " + num);
5        changeNum(num);
6        System.out.println("changeNum()⽅法调⽤之后:num = " + num);
7    }
8
9    public static void changeNum(int x) {
10        x = 2;
11    }
12 }
运⾏结果:
传递过程的⽰意图如下:
分析:num作为参数传递给changeNum()⽅法时,是将内存空间中num所指向的那个存储单元中存放的值1复制了⼀份传递给了changeNum()⽅法中的x变量,⽽这个x变量也在内存空间中分配的⼀个存储单元。这时就把num对的值1传递给了x变量所指向的存储单元中。此后在changeNum()⽅法中对x变量的⼀切操作都是针对于x所指向的这个存储单元,与num所指向的存储单元⽆关。
所以,在changeNum()⽅法被调⽤后,num所指向的存储单元的值还是没有发⽣变化,这就是所谓的“值传递”。
值传递的精髓是:传递的是存储单元中的内容,⽽不是存储单元的引⽤。
2.引⽤类型的参数
⽰例1:
1  public class TransferTest
2 {
2    public static void main(String[] args) {
3        Person person = new Person();
4        System.out.println(person);
5        change(person);
6        System.out.println(person);
7    }
8
9    public static void change(Person p) {
10        p = new Person();
11    }
12 }
13
14 /**
15  * Person类
16  */
17 class Person {
18
19 }
运⾏结果:
可以看出两次打印结果⼀致。即调⽤change()⽅法后,person变量并没发⽣改变。
传递过程的⽰意图如下:
分析:
01.当程序执⾏到第3⾏ Person person = new Person()时,程序在堆内存(heap)中开辟了⼀块内存空间⽤来存储Person类实例对象,同时在栈内存(stack)中开辟了⼀个存储单元来存储该实例对象的引⽤,即上图中person指向的存储单元。
02.当程序执⾏到第5⾏ change(person)时,person作为参数(实参)传递给饿了change()⽅法。这⾥是person将⾃⼰的存储单元的内容传递给了change()⽅法的p变量。此后在change()⽅法中对p变量的⼀切操作都是针对于p变量所指向的存储单元,与perosn所指向的存储单元就没有关系了。
⽰例2:
1 public class P {
2    String name = "P";
3    public P(String name) {
4        this.name = name;
5    }
6    @Override
7    public String toString() {
8        return name;
9    }
10 }
11
12 public class Test {
13    static P p1 = new P("p1");
java的tostring方法
14    public static void main(String[] args) {
15        P p = new P("P");
16      System.out.println("before change p:" + p.toString);
17        changeObj(p);
18        System.out.println("after change p:" + p.toString());
19    }
20
21    static void changeObj(P p) {
22        p = new P("pp");
23        System.out.println("change p:" + p.toString());
24        //p = p1;
25        //System.out.String());
26    }
27 }
运⾏结果:
⾸先要理解 “=” 赋值操作的意义:
对于基本数据类型来说 “=”赋值操作是直接改变内存地址(存储单元)上的值。
对于引⽤类型来说 “=” 赋值操作是改变引⽤变量所指向的内存地址(上⽂中存储单元)。
调⽤changeObj()⽅法进⼊第21⾏:
执⾏22⾏后:
所以对外部的p变量是没有影响的。
总结:
函数参数传递其实是⼀个赋值的过程,基本类型传递的是数值,引⽤类型传递的引⽤对象的内存地址。另外⼀点要特别注意,函数的参数其实是函数内部的局部变量。不要跟外部变量混淆。
⽰例3:
1 package cn.canshu;
2 class Person{
3    private int id;
4    private String name;
5    public Person(int id,String name) {
6        this.id = id;
7        this.name = name;
8    }
9 }
10 public class Demo02 {
11    public static void main(String[] args) {
12        Person a = new Person(23, "a");
13        Person b = new Person(22,"b");
14        System.out.println("交换前\na:"+a+"\nb:"+b);
15        swap(a, b);
16        System.out.println("交换后\na:"+a+"\nb:"+b);
17    }
18    private static void swap(Person a, Person b) {
19        Person temp = a;
20        a = b;
21        b = temp;
22    }
23 }
运⾏结果:
同理,外部的ab引⽤不是内部的ad引⽤,故不会发⽣改变。
我们可以发现,Java⽅法的传值,实际上是把实参的值—-对象引⽤(对象的内存地址)传递给了形参,从⽽形参和实参的值(即变量⾥存储的内存地址,⾮变量本⾝的内存地址)是相同的,指向了同⼀个对象/内存地址。
===================================我是分割线
==========================================================================================
⽰例4
class Person{
private int id;
private String name;
public Person(int id,String name) {
this.id = id;
this.name = name;
}
//省略get,set⽅法
  //省略toString⽅法
}
public void demo(){
Person person = new Person("张三",1);
 sout(person);
 demo2(person);
 sout(person);
}
public void demo2(Person person1){
person.setName ="李四"
person.setId=2
  sout(person1)
}
运⾏结果:
改变前:person{name=‘张三’,age=1}
    person{name=‘李四’,age=2}
改变后:person{name='李四',age=2}
把person对象的地址的引⽤传给了person1 ,所以person和person1指向的是同⼀个内存地址。
总结⼀下:JAVA⽅法的传值,基本数据类型是值传递,引⽤数据类型(不包含String类型)是值传递【地址值的传递】,如果⽅法⾥有person1=new Person【new对象】,或者是给对象person1赋值了⼀个地址值。原来的(person)对象不改变,如果只是改变person1的属性,person的属性值也会跟着改变。
如果有疏漏,请指正(* ̄︶ ̄)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。