【8】java之引用传递

一、引用传递

引用传递是整个 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 int getInfo(){
		return this.num;
	}
}

public class TestDemo{
	public static void main(String args[]){
		Message msg = new Message(30);
		// 引用传递
		fun(msg); 
		System.out.println(msg.getNum());
	}
	public static void fun(Message temp){
		temp.setNum(100);
	}
}

以上程序输出:100。

范例:第二道引用传递

public class TestDemo{
	public static void main(String args[]){
		String msg = "Hello";
		// 引用传递
		fun(msg); 
		System.out.println(msg);
	}
	public static void fun(String temp){
		temp = "World";
	}
}

​ 以上输出:Hello,题目只有一个解决思路:String 类对象内容一旦声明则不可改变,对象内容的改变依靠的是引用关系的变更。

范例:第三道引用传递

class Message{
	private String info = "nihao";
	public Message(String info){
		this.info = info;
	}
	public void setInfo(String info){
		this.info = info;
	}
	public String getInfo(){return this.info;}
}

public class TestDemo{
	public static void main(String args[]){
		Message msg = new Message("Hello");
		// 引用传递
		fun(msg); 
		System.out.println(msg.getInfo());
	}

	public static void fun(Message temp){
		temp.setInfo("World");
	}
}

输出:World。但是以上的内存描述并不严格,因为在程序里,info 也是一个 String 类的对象。

结论:虽然 String 属于类,属于引用类型,但是由于其内容不可改变的特点,很多情况把 String 类型当成基本数据类型那样使用,也就是说:每一个 String 变量只能够保存一个数据。

总结:这三个引用范例算是一个小小的总结,也算是彻底阐述了 String 类的特点:不能改变。

二、引用传递实际应用

假如说,每一个人都有一辆车或没有汽车。如果设计满足以上数据存储的数据库,应该设计两张表:汽车表和人员表。

那么换回到程序思路,如果说现在想定义类,那么也应该定义两个类,所以通过分析可以发现以下的神奇规律:

简单 Java 类的编写原则:

  • 类名称 = 表名称;
  • 属性名称(类型) = 表字段(类型);
  • 一个实例化对象 = 一行记录;
  • 多个实例化对象(对象数组) = 多行记录;
  • 引用关系 = 外键约束。

范例:代码设计如下

class Member{
	private int mid;
	private String name;
}
class Car{
	private String cname;
}

以上实现了两个独立的类,并且没有外键关系,但是在表中可以通过外键描述关系,那么在类之中可以采用引用描述这个关系

class Member{
	private int mid;
	private String name;
	/* 表示属于人的车
		如果 Car 有实例化对象则表示人有车;
		如果 car 为 null 则表示人没有车。
	*/
	private Car car; 
	public String getInfo(){
		return "编号:" + this.mid + ", 姓名:" + this.name;
	}
}
class Car{
	private String cname;
	private Member member;  // 车属于一个人
	public Car(String name){
		this.cname = name;
	}
	public String getInfo(){
		return "汽车名字:" + this.cname;
	}
}

一定要记住,Member 和 Car 应该都是一个独立的对象,而后通过产生对象发生关系。

当 Member 或 Car 类的对象产生之后,那么就应该为这两个对象设置彼此的关系。

class Member{
	private int mid;
	private String name;
	/* 表示属于人的车
		如果 Car 有实例化对象则表示人有车;
		如果 car 为 null 则表示人没有车。
	*/
	private Car car; 
	public Member(int mid,String name){
		this.mid = mid;
		this.name = name;
	}
	public void setCar(Car car){
		this.car = car;
	}
	public Car getCar(){
		return this.car;
	}
	public String getInfo(){
		return "编号:" + this.mid + ", 姓名:" + this.name;
	}
}
class Car{
	private String cname;
	private Member member;  // 车属于一个人
	public Car(String name){
		this.cname = name;
	}
	public void setMember(Member member){
		this.member = member;
	}
	public Member getMember(){
		return this.member;
	}
	public String getInfo(){
		return "汽车名字:" + this.cname;
	}
}
public class TestDemo{
	public static void main(String args[]){
		Member member = new Member(1,"King");
		Car car = new Car("宝马");
		member.setCar(car);
		car.setMember(member);
		System.out.println(member.getCar().getInfo());
		System.out.println(car.getMember().getInfo());
	}
}

以上的程序类完成之后,下面需要对程序进行测试,但是对程序的测试要求分两步:

  • 第一步:根据定义的结构关系设置数据;
  • 第二步:根据定义的结构关系取出数据。
public class TestDemo{
	public static void main(String args[]){
		// 第一步:设置数据
		Member member = new Member(1,"King"); // 独立对象
		Car car = new Car("宝马"); // 独立对象
		member.setCar(car);	// 一个人有一辆车
		car.setMember(member); // 一辆车属于一个人
		// 第二步:取出数据
		System.out.println(member.getCar().getInfo()); // 通过人找到车的信息
		System.out.println(car.getMember().getInfo()); // 通过车找到人的信息
	}

下面进一步设计,例如:每个人都有自己的孩子,孩子还可能有车。

class Member{
	private int mid;
	private String name;
	/* 表示属于人的车
		如果 Car 有实例化对象则表示人有车;
		如果 car 为 null 则表示人没有车。
	*/
	private Car car; 
	private Member child;
	public Member(int mid,String name){
		this.mid = mid;
		this.name = name;
	}
	public void setCar(Car car){
		this.car = car;
	}
	public Car getCar(){
		return this.car;
	}
	public void setChild(Member child){
		this.child = child;
	}
	public Member getChild(){
		return this.child;
	}
	public String getInfo(){
		return "编号:" + this.mid + ", 姓名:" + this.name;
	}
}

class Car{
	private String cname;
	private Member member;  // 车属于一个人
	public Car(String name){
		this.cname = name;
	}
	public void setMember(Member member){
		this.member = member;
	}
	public Member getMember(){
		return this.member;
	}
	public String getInfo(){
		return "汽车名字:" + this.cname;
	}
}

public class TestDemo{
	public static void main(String args[]){
		// 第一步:设置数据
		Member member = new Member(1,"King"); // 独立对象
		Car car = new Car("宝马"); // 独立对象
		member.setCar(car);	// 一个人有一辆车
		car.setMember(member); // 一辆车属于一个人

		Member child = new Member(2,"KAlice"); //一个孩子
		Car carc = new Car("法拉利"); // 一辆车
		member.setChild(child); // 一个人有一个孩子
		child.setCar(carc); // 一个孩子有一辆车
		carc.setMember(child); // 一辆车属于一个人
		// 第二步:取出数据
		System.out.println(member.getCar().getInfo()); // 通过人找到车的信息
		System.out.println(car.getMember().getInfo()); // 通过车找到人的信息
		System.out.println(member.getChild().getInfo()); // 通过人找到孩子的信息;
		System.out.println(member.getChild().getCar().getInfo()); // 通过人找到孩子的车子信息;
	}
}

现实中这样的操作其实很常见:一个人有一间房子、一个人有一张身份证、一个人有一个驾照......

还可以针对引用做进一步的描述,例如:要求描电脑,电脑由主机、显示器、键盘、CPU、鼠标、内存、硬盘、显卡组成。那么现在怎么通过代码描述呢?

以下是伪代码

class 键盘{}
class 鼠标{}
class 硬盘{}
class 显示器{}
class 主板{}
class 主机{
	private 硬盘 对象[];
	private CPU 对象[];
	private 主板 对象;
	private 内存 对象[];
}
class 电脑{
	private 主机 对象;
	private 显示器 对象[];
	private 鼠标 对象;
}

这样的设计思路在 Java 之中称为合成设计模式。合成设计的关键:占着各自对象类型。

posted @ 2022-06-17 15:07  才华充电中  阅读(1036)  评论(0编辑  收藏  举报