【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 之中称为合成设计模式。合成设计的关键:占着各自对象类型。