Java 程序设计语言总是采用按值调用

2021-11-04 0 By admin

方法可以修改传递引用所对应的变量值 , 而不能修改传递值调用所对应的变量值。

  1. 按值调用(call by value)表示方法接收的是调用者提供的值。
  2. 按引用调用( call by reference )表示方法接收的是调用者提供的变量地址。

Java 程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个副本。具体来讲,方法不能修改传递给它的任何参数的内容。

Java 核心技术 卷1

一、证明 Java 方法是按值调用的

1.1、基本数据类型的方法参数

基本数据类型的参数是按值调用的,这个比较容易理解;在方法中修改接受到的基本数据类型的参数,并不能对方法外的数据有影响。

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

执行说明:swap方法并未改变x,y的值;执行完swap方法后,swap弹栈,变量temp,a,b随之消失。

1.2、引用数据类型的方法参数-1

引用数据类型的方法参数,在方法中可以修改引用类型中的属性或元素等。

public static strictfp void main(String[] args) {
  Person x = new Person("张三");
  change(x);
  System.out.println("x:"+x.name);//x:李四
}
private static void change(Person a) {
  a.name = "李四";
}

执行说明:a为x值的一个拷贝,这里是一个对象引用,a和x同时指向一个Person对象。

1.3、引用数据类型的方法参数-2

引用数据类型的方法参数,在方法中不能修改引用对象本身的内存指向。

public static strictfp void main(String[] args) {
  Employee alice = new Employee("alice");
  Employee bob = new Employee("bob");
  swap(alice, bob);
  System.out.println("alice:"+alice.name+",bob:"+bob.name); //alice:alice,bob:bob
}
public static void swap(Employee x,Employee y){
  Employee temp = x;
  x = y;
  y = temp;
}

执行说明:方法并没有改变存储在变量 alice 和 bob 中的对象引用。在swap方法结束时参数变量x 和 y 被丢弃了。

交换对象参数没有持久效果
交换对象参数没有持久效果

下面总结一下 Java 中方法参数的使用情况 :

  1. 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
  2. 一个方法可以改变一个对象参数的状态 。
  3. 一个方法不能让对象参数引用一个新的对象。

二、方法参数的测试题

2.1、按值调用示例1

public class IoTest {
  public static void main(String[] args) throws IOException {
    List<String> a = null;
    test(a);
    System.out.println(a.size()); // exception in thread    NullPointerException
  }
  public static void test(List<String> a) {
    a = new ArrayList<String>(); // 按值调用的接受变量的引用地址修改了。
    a.add("abc");
  }
}

2.2、按值调用示例2

public class IoTest {
  public static void main(String[] args) throws IOException {
    StringBuffer a = new StringBuffer("A");
    StringBuffer b = new StringBuffer("B");
    operator(a,b);
    System.out.println(a+","+b); //AB,B
  }
  public static void operator(StringBuffer x,StringBuffer y){
    x.append(y);//x引用所指向的对象其中的值被改变
    y=x;//y引用所指向的对象不会发生变化
  }
}