一、引用传递
引用传递是整个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 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); } }
范例:第二道引用传递范例
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"; } }
以上的题目只有一个解决思路: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"); } }
但是以上的内存描述并不严格,因为在程序里面,info也是一个String类的对象,所以要想描述的更加清楚,应该采用如下的内存关系图:
结论:虽然String属于类,属于引用类型,但是由于其内容不可改变的特点,很多的时候就直接把String当成基本数据类型使用,即:每一个String变量只能够保存一个数据。
二、引用传递实际应用
假如说,每一个人都有一辆车或没有车,要求可以通过面向对象的方式描述以上的关系。
下面先抛开Java不看,如果说现在要求你来设计可以满足以上数据存储的数据库,创建语句:
应该设计出两张表:人员表和汽车表。如果换回到程序思路,也应该创建两个类。
简单Java类的编写原则:
· 类名称 = 表名称;
· 属性名称(类型) = 表字段(类型);
· 一个实例化对象 = 一行记录;
· 多个实例化对象(对象数组) = 多行记录;
· 引用关系 = 外键约束;
范例:代码设计如下
class Member {
private int mid;
private String name;
}
class Car {
private String pname;
}
以上实现了两个独立的类,并且没有任何的外键关系,但是在表中可以通过外键描述关系,那么在类之中可以采用引用来描述关系。
class Member {
private int mid;
private String name;
// car有实例化对象表示有车
// car为null表示没有车
private Car car;// 表示属于人的车
}
class Car {
private Member member;// 车属于一个人
private String pname;
}
一定要记住的是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 String getInfo() {
return "人员编号:" + mid + ",姓名:" + name;
}
}
class Car {
private Member member;// 车属于一个人
private String pname;
public Car(String pname) {
this.pname = pname;
}
public String getInfo() {
return "车的名字:" + pname;
}
}
当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 String getInfo() {
return "人员编号:" + mid + ",姓名:" + name;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return this.car;
}
}
class Car {
private Member member;// 车属于一个人
private String pname;
public Car(String pname) {
this.pname = pname;
}
public String getInfo() {
return "车的名字:" + pname;
}
public void setMember(Member member) {
this.member = member;
}
public Member getMember() {
return this.member;
}
}
以上的程序类完成之后,下面需要对程序进行测试,但是程序的测试要求分两步:
· 第一步:根据定义的结构关系定义数据;
· 第二步:根据定义的结构关系取出数据;
public class TestDemo {
public static void main(String args[]) {
// 第一步:设置数据
Member m = new Member(1, "张艺兴");// 独立对象
Car c = new Car("奔驰");// 独立对象
m.setCar(c);// 一个人有一辆车
c.setMember(m);// 一辆车属于一个人
// 第二步:取出关系
// 通过人找到车的信息
System.out.println(m.getCar().getInfo());
// 通过车找到人的信息
System.out.println(c.getMember().getInfo());
}
}
下面可以进一步的设计,例如:每个人都有自己的孩子,孩子还可能有车。那么有两种设计方法:
-
方法一:设计一个孩子类,如果有孙子,设计一个孙子类,如果有……
- 方法二:一个人的孩子一定还是一个人,与人的类本质没有区别,可以在Member类里面设计一个属性表示孩子,其类型就是Member。
class Member { private int mid; private String name; private Member child;// 表示孩子 // car有实例化对象表示有车 // car为null表示没有车 private Car car;// 表示属于人的车 public Member(int mid, String name) { this.mid = mid; this.name = name; } public String getInfo() { return "人员编号:" + mid + ",姓名:" + name; } public void setChild(Member child) { this.child = child; } public Member getChild() { return this.child; } public void setCar(Car car) { this.car = car; } public Car getCar() { return this.car; } } class Car { private Member member;// 车属于一个人 private String pname; public Car(String pname) { this.pname = pname; } public String getInfo() { return "车的名字:" + pname; } public void setMember(Member member) { this.member = member; } public Member getMember() { return this.member; } } public class TestDemo { public static void main(String args[]) { // 第一步:设置数据 Member m = new Member(1, "张艺兴");// 独立对象 Member chd = new Member(2, "欢欢"); Car c = new Car("奔驰");// 独立对象 Car cc = new Car("法拉利"); m.setCar(c);// 一个人有一辆车 c.setMember(m);// 一辆车属于一个人 chd.setCar(cc); cc.setMember(chd); m.setChild(chd); // 第二步:取出关系 // 通过人找到车的信息 System.out.println(m.getCar().getInfo()); // 通过车找到人的信息 System.out.println(c.getMember().getInfo()); // 通过人找到孩子 System.out.println(m.getChild().getInfo()); // 通过人找到他孩子的车 System.out.println(m.getChild().getCar().getInfo());//代码链 } }
还可以针对于引用做进一步的描述,例如:要求描述电脑,电脑由主机、显示器、键盘、内存、CPU、硬盘、显卡组成,那么怎么通过代码描述呢?
class 键盘{} class 鼠标{} class CPU{} class 硬盘{} class 内存{} class 显示器{} class 主板{} class 主机{ private CPU 对象[]; private 硬盘 对象[]; private 主板 对象; private 内存 对象[]; } class 电脑{ private 主机 对象; private 显示器 对象[]; private 键盘 对象; private 鼠标 对象; }
这样的设计思路在Java之中称为合成设计模式。
面向对象的设计方式应该说所有的设计思路来源于现实。
引用是实现两个不同类型之间互相关联的主要手段。