Java
from 《Java 核心技术第10版》4.5方法参数
按值调用 call by value : 方法不可修改传递值调用所对应的变量值
按引用调用 call by reference : 方法可修改传递引用所对应的变量值
Java 只有按值调用,方法得到参数值的拷贝,不能修改传参的变量内容
方法参数(传参)类型:
- 基本数据类型
- 对象引用类型
/**
* This program demonstrates parameter passing in Java.
*/
public class ParamTest {
public static void main(String[] args) {
// Test1: 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);
// Test2: 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());
// Test3: 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("After: b=" + b.getName());
swap(a, b);
System.out.println("Before: a=" + a.getName());
System.out.println("After: b=" + b.getName());
}
public static void tripleValue(double x) { // doesn't work
x *= 3;
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 t = x;
x = y;
y = t;
System.out.println("End of method: x=" + x.getName());
System.out.println("End of method: y=" + y.getName());
}
}
class Employee {
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;
}
}
______________________________________________________
Testing tripleValue:
Before: percent=10.0
End of method: x=30.0
After: percent=10.0
Testing tripleSalary:
Before: salary=50000.0
End of method: salary=150000.0
After: salary=150000.0
Testing swap:
Before: a=Alice
After: b=Bob
End of method: x=Bob
End of method: y=Alice
Before: a=Alice
After: b=Bob
Process finished with exit code 0
- Test1
没保留对值参数的修改 -> 方法得到的是参数值的拷贝,不能修改参数变量内容 - Test2
保留了对对象参数的修改 -> 方法得到的是对象引用的拷贝,对象引用及其它的拷贝同时引用同一个对象 - Test3
没保留交换对象参数的结果 -> swap参数x、y被初始化为2个对象引用的拷贝,交换的是2个拷贝 -> 实际上对象引用是按值传递的(String属于对象引用类型)
总结
- 方法不能修改基本数据类型参数(数值型/布尔型)
- 方法可以改变对象参数的状态
- 方法不能让对象参数引用一个新的对象
C++
C++ 有值调用和引用调用,引用参数标有 ‘&’
可轻松实现void tripleValue(double& x)
或void swap(Employee& x, Employee& y)
修改其引用参数的目的
#include <bits/stdc++.h>
using namespace std;
void f1(int a) { a=1; } // 传值 实参拷贝给形参
void f2(int *a) { *a=1; } // 传指针 形参以分配指针变量的形参来存放实参传入的地址
void f3(int& a) { a=1; } // 传引用 直接把形参作为实参的一个别名,形参不会另外分配内存来存放实参传入的地址
int main() {
int a = 0;
cout<<"Before: a="<<a<<endl;
f1(a);
cout<<"After f1: a="<<a<<endl;
a = 0;
f2(&a);
cout<<"After f2: a="<<a<<endl;
a = 0;
f3(a);
cout<<"After f3: a="<<a<<endl;
return 0;
}
______________________________________________________
Before: a=0
After f1: a=0
After f2: a=1
After f3: a=1
指针 - 某块内存的地址,是一个数值,可以为0(空指针 - 指针可以不指向任何东西)
引用 - 一个变量的别名,不能存在空引用(外号一定是"某个存在的物体"的外号)