在C/C++中,值传递和指针传递是一组概念,两者作为参数用于不同的场合,也可能会有不同的使用效果。而与之对应的,JAVA中的对应概念就是引用传递。这里通过几个例子来说明一下应用传递在不同场景中的使用。
场景一:int
先看一段代码:
public class Demo {
public static void main(String args[]) {
int num = 10;
func(num);
System.out.println("Num is " + num);
}
public static void func(int var) {
var = 100;
}
}
结果为:
Num is 10
int类型为基本数据类型,在基本数据类型中,不存在为该变量在堆内存上开辟空间进行存储。因此main中的num和func中的var都属于栈内存,两者指向不同的位置,因此将num的值赋给var只是改变了var对应的栈内存的值,而func调用结束,var对应的内存释放,num仍然是10。
场景二:String
先看一段代码:
public class Demo {
public static void main(String args[]) {
String str = "Hello";
func(str);
System.out.println("Str is " + str);
}
public static void func(String var) {
var = "world";
}
}
结果为:
Str is Hello
JAVA中会对字符串在堆内存上开辟空间进行存储,因此Hello和world都在堆内存上有自己的空间,而str指向Hello,在func调用后,var也指向Hello,随后var的指向变为了world,但str的指向并没有发生变化,因此在func调用结束后,var释放掉,str仍然为Hello。
场景三:int属性
首先定义一个Book类:
class Book {
private String name;
private int price;
public Book() {
System.out.println("This is Book's constructer.");
}
public Book(String name, int price) {
this.name = name;
this.price = price;
}
public void getInfo() {
System.out.println("Book name is " + name + ",book price is " + price);
}
public void setName(String var) {
name = var;
}
public String getName() {
return name;
}
public void setPrice(int var) {
price = var;
}
public int getPrice() {
return price;
}
}
再看一段代码:
public class Demo {
public static void main(String args[]) {
Book bk = new Book("English",10);
func(bk);
System.out.println("Num is " + bk.getPrice());
}
public static void func(Book var) {
var.setPrice(20);
}
}
结果为:
Num is 20
在上面的代码中,首先实例化了Book对象bk,bk.name指向English,bk.price指向10,然后调用func,使var和bk指向堆内存中相同的Book对象,然后通过var设置该Book对象price属性的值,因为int是基本数据类型,便直接修改了堆内存中的值,因此此时的bk.getPrice()结果为20。
场景四:String属性
先看一段代码:
public class Demo {
public static void main(String args[]) {
Book bk = new Book("English",10);
func(bk);
System.out.println("str is " + bk.getName());
}
public static void func(Book var) {
var.setName("Math");
}
}
结果为:
str is Math
和上个场景是相似的,无非是在func中修改了函数体的内容。不过此时Math作为匿名对象传递,同样会存储在堆内存中,而setName方法的调用则是修改了bk中Name指向的堆内存。因此结果为Math。
上述几种场景其实也好区分:
- 注意栈内存中变量的指向关系
- 注意堆内存中变量的实际存储
- 注意方法调用前后栈内存的建立和释放