Java优秀的面向对象意识成为后续语言不断模仿的对象,而JAVA引用数据传递可谓是无法让初学者能理解的,探寻根本原因背后有数据结构的本质。博主本次采用案例式讲解引用数据传递,文末并附有源码,大家可私下尝试!

代码前的准备

创建一个Book类,类里有它的价格和它的书名。

class Book{
	String title;
	double price;
	public void getInfo() {
		System.out.println("图书名称:" + title + ",价格:" + price);
	}
}

案例1–声明并实例化对象

案例1主要讲述初学者常用的是这种方式声明并实例化对象,一条语句却有引用的概念。先看这个案例,案例就是初始化一个对象,并设置一个概念,非常直观。这里用到类,代码下方对类做简要介绍。

public  void main1(String args[]) {
		Book bk = new Book();
		bk.title = "Java开发";
		bk.price = 89.9;
		bk.getInfo();
	}

一般的类定义完成后,肯定无法直接使用,如果要使用,必须依靠对象,由于类属于引用数据类型,所以对象的产生格式如下

类名称 对象名称 = new 类名称();

如果分布完成,那就先声明,后实例

声明对象: 类名称 对象名称 = null;
实例化对象: 对象名称 = new 类名称();

案例2–分步实例化对象

public void main2(String args[]) {
		Book bk = null;//声明对象 先声明对象用栈内存指向空的堆内存
		bk = new Book(); //实例化对象
		bk.title = "Java开发";
		bk.price = 89.9;
		bk.getInfo();
	}

这段代码,先声明后实例化,提到了一个栈内存和堆内存的概念。栈内存创建地址,堆内存创建空间。用地址指向空间,可以说是c的指针范畴。画张图加强理解

java实例 java的实例_堆内存


这也就是分步骤,那么问题来了?如果直接不实例化用代码会怎样,下面看这段代码

案例3–分布但不实例化对象

public void main3(String args[]) {
		Book bk = null;//声明对象 先声明对象用栈内存指向空的堆内存
		bk = new Book(); //实例化对象
		bk.title = "Java开发";
		bk.price = 89.9;
		bk.getInfo();
	}

代码当然会抛异常,这个异常是在使用引用数据类型时没有为其开辟堆内存空间。异常情况怎么样?来张图

java实例 java的实例_实例化_02

案例4–声明并实例化两个对象

一个对象会声明并实例化,两个肯定也会,那就直接用吧

public  void main4(String args[]) {
		Book bkA = new Book();
		Book bkB = new Book();
		bkA.title = "Java开发";
		bkA.price = 89.9;
		bkA.getInfo();		
		bkB.title = "Web开发";
		bkB.price = 19.9;
		bkB.getInfo();			
	}

这段代码也可以认为对第一个对象的copy,只要把title和price改变就行了,问题来了,如果对象产生引用,也就是两个实例化对象相等会发生什么?

案例5–对象之间引用传递

public void main5(String args[]) {
		Book bkA = new Book();
		Book bkB = null;
		bkA.title = "Java开发";
		bkA.price = 89.9;
		bkB = bkA;
		bkB.price = 69.9;
		bkA.getInfo();			
	}

代码运行,b的价格改变A的价格也跟着改变,运行结果如下

java实例 java的实例_堆内存_03


为什么?因为同时开辟堆内存,栈内存指向同一个堆内存地址。堆内存改变,地址不发生改变,也就值会一起改变 大家如果不理解,也可以来张图来观察一下

java实例 java的实例_Java_04


理解了这张图之后,然后再去观察如果两个对象实例化开始不同,结果在中间产生引用传递,一个值改变,那么另一个值肯定改变!再去看最后一个例子

案例6–深入观察

public static void main(String args[]) {
		Book bkA = new Book();
		Book bkB = new Book();
		bkA.title = "Java开发";
		bkA.price = 89.9;
		
		bkB.title = "JSP开发";
		bkB.price = 19.9;
		bkB = bkA;
		bkB.price = 100.2;
		bkA.getInfo();	
		
		
	}

代码运行效果

java实例 java的实例_实例化_05


引用传递后的,之前开辟的内存就会被垃圾回收器析构,下面这张图加深巩固理解

java实例 java的实例_Java_06

附完整源码

如果对java不了解,就是每一个案例的代码复制到void main函数运行,因为main函数是入口。我的类名称是Main,大家自己的可以修改哟!

package test;

class Book{
	String title;
	double price;
	public void getInfo() {
		System.out.println("图书名称:" + title + ",价格:" + price);
	}
}
public class Main {
	public  void main1(String args[]) {
		Book bk = new Book();
		bk.title = "Java开发";
		bk.price = 89.9;
		bk.getInfo();
	}
	public void main2(String args[]) {
		Book bk = null;//声明对象 先声明对象用栈内存指向空的堆内存
		bk = new Book(); //实例化对象
		bk.title = "Java开发";
		bk.price = 89.9;
		bk.getInfo();
	}
	public void main3(String args[]) {
		Book bk = null;//声明对象 先声明对象用栈内存指向空的堆内存
		//bk = new Book(); //实例化对象
		bk.title = "Java开发";
		bk.price = 89.9;
		bk.getInfo();
	}
	public  void main4(String args[]) {
		Book bkA = new Book();
		Book bkB = new Book();
		bkA.title = "Java开发";
		bkA.price = 89.9;
		bkA.getInfo();		
		bkB.title = "Web开发";
		bkB.price = 19.9;
		bkB.getInfo();			
	}
	public void main5(String args[]) {
		Book bkA = new Book();
		Book bkB = null;
		bkA.title = "Java开发";
		bkA.price = 89.9;
		bkB = bkA;
		bkB.price = 69.9;
		bkA.getInfo();			
	}
	public static void main(String args[]) {
		Book bkA = new Book();
		Book bkB = new Book();
		bkA.title = "Java开发";
		bkA.price = 89.9;
		
		bkB.title = "JSP开发";
		bkB.price = 19.9;
		bkB = bkA;
		bkB.price = 100.2;
		bkA.getInfo();	
		
		
	}
}

总结

本博文采用六个案例,第一个案例是最寻常使用,第二个分步声明实例化对象。第三个分步骤但不实例化的后果大家会看到异常,第四个声明并实例化两个对象,第五个对象之间引用传递,理解堆内存与栈内存的深层次意义,并附图理解,案例六代码垃圾析构器的使用。

希望博文能对大家有帮助!