引用传递是Java的精髓,核心意义在于:
同一块堆内存空间可以被不同的栈内存空间指向,不同栈内存可以对同一堆内存进行内容修改。
目录
程序一
程序二
程序三
总结
程序一
class Message{
private int num=10;
public Message(int num) {
this.num=num;
}
public void setNum(int num) {
this.num=num;
}
public int getNum() {
return this.num;
}
}
public class STATIC {
public static void main(String[] args) {
Message msg=new Message(30);
fun(msg);//引用传递
System.out.println(msg.getNum());
}
//外部函数fun() 加static原因是主函数是static,想调用外部函数也得static
public static void fun(Message temp) {
temp.setNum(100);
}
}
//程序结果:100
内存分析:
首先通过Message类的构造函数给属性num赋值,然后在主程序中调用fun()方法,fun()方法的参数是Message类对象的引用,内存会为它开辟一个栈内存,然后和msg指向同一存储num值的堆内存
,然后fun()函数执行修改num值为100的操作,在执行结束后,断开连接。
程序二
public class STATIC {
public static void main(String[] args) {
String msg="hello world!";
fun(msg);//引用传递
System.out.println(msg);
}
//外部函数fun()
public static void fun(String temp) {
temp="no thank";
}
}
//运行结果:hello world!
内存分析:
分析:堆内存遇见常数和“字符串”会开辟空间存储,执行fun(msg)时,先把temp指向msg的堆内存内容,然后在执行temp=“world”时,temp会断开原来的指向,转而建立新开辟的world内容的连接,所以fun()执行完毕后系统回收temp和无指向的world,导致msg指向内容没有改变。
public class STATIC { public static void main(String[] args) { int msg=10; fun(msg); System.out.println(msg); } //外部函数fun() public static void fun(int temp) { temp=100; } }
同理:程序执行结果是:10;方法同String.
调用fun(msg)时候,temp指向了保存msg内容的堆内存,但是:执行:temp=100时,堆内存开辟空间存储100,temp断开了原来的指向,指向了新的100的内存空间。
程序三
class Message{
private String info="此内容无用";
public Message(String info) {
this.info=info;
}
public void setInfo(String info) {
this.info=info;
}
public String getInfo() {
return this.info;
}
}
public class STATIC {
public static void main(String[] args) {
Message msg=new Message("hello");
fun(msg);//引用传递
System.out.println(msg.getInfo());
}
//外部函数fun()
public static void fun(Message temp) {
temp.setInfo("world");
}
}
//运行结果是:world (fun()函数成功修改了info的内容)
内存分析:
左上图:String也是一个类,所以在执行构造函数时:堆内存存放了info的对象,然后栈内存指向了该属性,对象存放在栈内存,然后该对象指向了堆内存存放的“hello”内容
右上图:引用传递,temp指向了与msg相同的存储info对象的堆内存
左下图:首先堆内存会先开辟存储“world”的空间,由于执行的是setinfo,是对象info调用的,所以指向从“hello”变为“world”,断开旧连接,指向新连接。
右下图:执行完毕后,回收temp,hello没有指向,故而也会被回收。
一个String变量只可以保存一个内容。所以可以把String类视为基本类型(如:int),类比为直接在堆内存中赋值。
总结
所谓引用传递就是调用外部函数达到修改属性内容的目的,难点就在于修改值的成功与否的分析。
class Book{
private double price;
public Book(double price) {
this.price=price;
}
public void setPrice(double price) {
this.price=price;
}
public double getPrice() {
return this.price;
}
}
public class transfer {
public static void main(String[] args) {
// TODO Auto-generated method stub
Book a=new Book(99.9);
fun(a);
System.out.println(a.getPrice());
}
public static void fun(Book temp) {
temp.setPrice(199.88);
}
}
运行结果:199.88