方法参数的值调用+引用调用+深浅拷贝

来源:互联网 发布:caffe bene菜单 编辑:程序博客网 时间:2024/05/16 08:01

【0】README

0.1)本文描述+源代码均 转自 core java volume 1, 旨在理清值调用+引用调用;


【1】参数传递给方法的专业术语:

1.1)值调用:它表示方法接收的是调用者提供的值;
1.2)引用调用:它表示方法接收的是调用者提供的变量地址;

【2】看个荔枝:

2.1)设一个方法视图将一个参数值增大3倍:

public static void tripleValue(double x){    x = 3 * x;}

2.2)然后调用这个方法:

double percent = 10; tripleValue(percent);

这里写图片描述
2.3)无论如何,调用这个方法后,percent的值还是10,下面看一下具体执行过程:

  • step1) x 被初始化percent值的一个copy;
  • step2) x 被乘以 3 后等于 30, 但是 percent 仍然是 10;
  • step3) 这个方法结束后, 参数变量x 不在使用;
    这里写图片描述

【3】方法参数共有两种类型:

  • type1) 基本数据类型(数字、布尔值);
  • type2) 对象引用;

3.1)可以看到, 一个方法不可能修改一个基本数据类型的参数;
3.2)对象引用作为参数就不同了,可以很容易地利用下面的方法实现将一个雇员的薪水提高两倍:

package com.corejava;public class EmployeeTest {    public static void main(String[] args)     {        Employee e = new Employee(10);         Employee.tripleSalary(e);        System.out.println("salary = " + e.getSalary());    }}class Employee{    private double salary;    public Employee(double salary)    {        this.salary = salary;    }    public static void tripleSalary(Employee e)    {        e.raiseSalary(200);    }    public void raiseSalary(double x)    {        this.salary = this.salary * x / 100;    }    public double getSalary() {        return salary;    }   }打印结果为: salary=20.0

3.3)上述程序的具体调用过程为:

  • step1) x 被初始化为 harry值的拷贝, 这里是一个对象的引用;
  • step2) raiseSalary方法应用于这个对象引用, x 和 harry 同时引用的那个 Employee对象的薪水提高了200%;
  • step3) 方法结束后,参数变量x 不再使用, 当然,对象变量harry继续使用那个薪水涨了 200%的对象;
    这里写图片描述
    3.4) 读者已经看到,实现一个改变对象参数状态的方法并不是难事, 方法得到的是对象引用的copy, 对象引用和其它的copy同时引用同一个对象;

【4】再看个荔枝:

package com.corejava;public class EmployeeTestOne {    public static void main(String[] args) {        EmployeeOne a = new EmployeeOne("Alice");        EmployeeOne b = new EmployeeOne("Bob");        System.out.println("before:" + a.getName() + b.getName());        EmployeeOne.swap(a,b);        System.out.println("after:" + a.getName() + b.getName());    }}class EmployeeOne{    private String name;    public EmployeeOne(String name)    {        this.name = name;    }    public static void swap(EmployeeOne x, EmployeeOne y)    {        EmployeeOne temp = x;        x = y;        y = temp;    }    public String getName() {        return name;    }}打印结果为:before:AliceBobafter:AliceBob

4.1)显然, 方法并没有改变存储在变量 a 和 b 中的 对象引用;swap 方法的参数x 和 y 被初始化为两个对象引用的copy, 这个方法交换的是 两个拷贝;在方法结束时参数变量x 和 y 被丢弃了, 原来的变量 a 和 b仍然引用这个方法调用之前所引用的对象;这里写图片描述
4.2)这个过程说明: java程序设计语言对对象采用的不是引用调用, 实际上,对象引用进行的是 值传递;

【5】下面总结下 java 中方法参数的使用情况:

  • 5.1)一个方法不能修改一个基本数据类型的参数(数值型和布尔型);
  • 5.2)一个方法可以改变一个对象参数的状态;
  • 5.3)一个方法不能让对象参数引用一个新的对象;

【6】最后一个综合性荔枝:

/** * This program demonstrates parameter passing in Java. * @version 1.00 2000-01-27 * @author Cay Horstmann */public class ParamTest{   public static void main(String[] args)   {      /*       * Test 1: Methods can't modify numeric parameters       */      System.out.println("Testing tripleValue:");      double percent = 10;      System.out.println("Before: percent=" + percent);      tripleValue(percent);      System.out.println("After: percent=" + percent);      /*       * Test 2: Methods can change the state of object parameters       */      System.out.println("\nTesting tripleSalary:");      Employee harry = new Employee("Harry", 50000);      System.out.println("Before: salary=" + harry.getSalary());      tripleSalary(harry);      System.out.println("After: salary=" + harry.getSalary());      /*       * Test 3: Methods can't attach new objects to object parameters       */      System.out.println("\nTesting swap:");      Employee a = new Employee("Alice", 70000);      Employee b = new Employee("Bob", 60000);      System.out.println("Before: a=" + a.getName());      System.out.println("Before: b=" + b.getName());      swap(a, b);      System.out.println("After: a=" + a.getName());      System.out.println("After: b=" + b.getName());   }   public static void tripleValue(double x) // doesn't work   {      x = 3 * x;      System.out.println("End of method: x=" + x);   }   public static void tripleSalary(Employee x) // works   {      x.raiseSalary(200);      System.out.println("End of method: salary=" + x.getSalary());   }   public static void swap(Employee x, Employee y)   {      Employee temp = x;      x = y;      y = temp;      System.out.println("End of method: x=" + x.getName());      System.out.println("End of method: y=" + y.getName());   }}class Employee // simplified Employee class{   private String name;   private double salary;   public Employee(String n, double s)   {      name = n;      salary = s;   }   public String getName()   {      return name;   }   public double getSalary()   {      return salary;   }   public void raiseSalary(double byPercent)   {      double raise = salary * byPercent / 100;      salary += raise;   }}

这里写图片描述

0 0
原创粉丝点击