本次学习的目标
掌握三种引用传递的操作范例
掌握引用传递的应用
具体内容
1.三道引用范例
我们新建项目RefDemo,然后新建类RefDemo01
1.1范例一:
classDemo01{
inttemp=30 ;//这里为了方便,属性暂时不封装
}
publicclassRefDemo01 {
publicstaticvoidmain(String[] args) {
Demo01 d1 =newDemo01() ;//实例化Demo01对象,实例化之后里面的temp=10
d1.temp=50 ;//修改temp属性的内容
fun(d1);
}
publicstaticvoidfun(Demo01 d2){//此处的方法由主方法直接调用
d2.temp= 100;
}
}
运行结果:
这时我们可以看到,temp的值是改变了的。
下面我们来对这个范例进行内存分析:
首先,我们在实例化对象的时候,开辟了一个堆空间,储存temp属性=30,然后我们在主方法中,对temp进行修改为50,然后我们新建了方法fun()在主方法内可以直接调用,而fun()方法所引用的是Demo01中的d1,传给了d2,这时d1,d2所指向的空间是一样的。然后d2对temp进行了修改,执行完后,断开了链接,此时的temp属性的值保留了修改后的值。这跟我们之前讲的数组的引用传递是非常相似的,不难理解。
1.2范例二:
我们新建类RefDemo02
publicclassRefDemo02 {
publicstaticvoidmain(String args[]){
String str1 ="hello";//实例化字符串对象
fun(str1);//调用fun方法
}
publicstaticvoidfun(String str2){
str2 ="MLDN";//修改字符串内容
}
}
运行结果:
我们可以看到结果是没有改变的,下面我们队他进行内存分析
这里需要注意的事,因为String类的值是不可改变的,所以当我们调用fun()方法中str2要修改值时,由于一个栈只能指向一个堆,所以就会断开原先的指向,重新指向一个堆,然后膝盖str2的内容。所以str1的内容并没有修改保留下来。
1.3范例三:
新建类RefDemo03
classDemo02{
Stringtemp="hello";//定义一个属性
}
publicclassRefDemo03 {
publicstaticvoidmain(String args[]){
Demo02 d1 =newDemo02() ;//实例化Demo02对象
d1.temp="world";//修改temp属性的内容
fun(d1);//调用fun方法
}
publicstaticvoidfun(Demo02 d2){//此处的方法由主方法直接调用
d2.temp="MLDN";//修改temp的值
}
}
运行结果:
下面对范例三进行内存分析:
这里可以看到跟我们第一个范例是一样的,而我们第二个范例比较特殊,因为堆里面的内容是String类直接赋值的,而String是一个特殊的类,其内容是不可改变的。
2.接收本类引用
例如,我们新建RefDemo04
classDemo03{//定义Demo03类
privateinttemp= 30;//声明temp属性并封装
publicintgetTemp() {//getter方法
returntemp;
}
publicvoidsetTemp(inttemp) {//setter方法
this.temp= temp;
}
}
publicclassRefDemo04 {
publicstaticvoidmain(String[] args) {
Demo03 d1 =newDemo03();//实例化Demo03对象
d1.setTemp(50);//只能通过setter方法修改内容
d1.temp= 30 ;//如果这样修改内容,肯定会出现错误
}
}
运行结果:
因为此时d1是在Demo03类的外部,所以无法访问,那么如果现在按照引用传递的方式将其传入到其内部的话,就可以相当于自己接收本类的引用对象了。
我们修改一下:
classDemo03{//定义Demo03类
privateinttemp= 30;//声明temp属性并封装
publicvoidfun(Demo03 d2){//接收本类的引用
d2.temp= 60 ;//直接通过对象调用本类的私有属性
}
publicintgetTemp() {//getter方法
returntemp;
}
publicvoidsetTemp(inttemp) {//setter方法
this.temp= temp;
}
}
publicclassRefDemo04 {
publicstaticvoidmain(String[] args) {
Demo03 d1 =newDemo03();//实例化Demo03对象
d1.setTemp(50);//只能通过setter方法修改内容
d1.fun(d1);//此处把Demo03的对象传回到自己的类中
}
}
运行结果:
我们可以看到,只要是符合引用传递的语法,则可以向任意的地方传递;
3.范例讲解:一对一关系
实际上我们在使用引用传递时,还可以表示出生活中的场景,例如:一个人有一本书,一本书属于一个人。从这样一句话中可以得到这样的结论:人应该是一个具体的类、书也应该是一个具体的类,在人的类中应该存在一个属性表示书,在书的类中也应该存在一个属性表示人。
下面我们新建RefDemo05来表示这种场景
classPerson{//定义Person类
privateStringname;//姓名
privateintage;//年龄
privateBookbook;//一个人有一本书
publicPerson(String name,intage){//构造方法,两个属性
this.setName(name);
this.setAge(age);
}
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name= name;
}
publicintgetAge() {
returnage;
}
publicvoidsetAge(intage) {
this.age= age;
}
publicBook getBook() {
returnbook;
}
publicvoidsetBook(Book book) {
this.book= book;
}
}
classBook{//定义Book类
privateStringtitle;//标题
privatefloatprice;//价格
privatePersonperson;//一本书属于一个人
publicBook(String title,floatprice){//构造方法
this.setTitle(title);
this.setPrice(price);
}
publicString getTitle() {
returntitle;
}
publicvoidsetTitle(String title) {
this.title= title;
}
publicfloatgetPrice() {
returnprice;
}
publicvoidsetPrice(floatprice) {
this.price= price;
}
publicPerson getPerson() {
returnperson;
}
publicvoidsetPerson(Person person) {
this.person= person;
}
}
publicclassRefDemo05 {
publicstaticvoidmain(String[] args) {
Person per =newPerson("张三",30) ;//实例化对象
Book bk =newBook("Java基础",99.0f);
per.setBook(bk);//设置两个对象间的关系,一个人有一本书
bk.setPerson(per);//设置两个对象间的关系,一本书属于一个人
+",年龄:"+ per.getAge() +",书名:"+ per.getBook().getTitle()
+",价格:"+ per.getBook().getPrice());//通过人名找到书
+",价格:"+ bk.getPrice() +",人名:"+ bk.getPerson().getName()
+",年龄:"+ bk.getPerson().getAge());//通过书名找到人
}
}
运行结果:
可以看到我们应用在场景的这个基本关系。
下面我们进一步的深入进去,再添加一些关系进去:比如一个人有一个孩子,每个孩子还会有一本书,按照我们上面的思路,难道还有建多一个孩子的类吗?很明显这样是不可取的,因为孩子也是属于人的范围,所以我们只需要修改Person类即可,下面我们复制一下RefDemo05的代码,在RefDemo06进行修改,在类中增加一个自己的引用。
因为我们在Eclipse中,在同个项目中,不同类使用同样的类名是会报错的,所以我们也将Person改为Person1,Book改为Book1。
classPerson1{//定义Person类
privateStringname;//姓名
privateintage;//年龄
privateBook1book;//一个人有一本书
privatePerson1child;//一个人有一个孩子
publicPerson1(String name,intage){//构造方法,两个属性
this.setName(name);
this.setAge(age);
}
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name= name;
}
publicintgetAge() {
returnage;
}
publicvoidsetAge(intage) {
this.age= age;
}
publicBook1getBook() {
returnbook;
}
publicvoidsetBook(Book1book) {
this.book= book;
}
publicPerson1getChild() {
returnchild;
}
publicvoidsetChild(Person1child) {
this.child= child;
}
}
classBook1{//定义Book类
privateStringtitle;//标题
privatefloatprice;//价格
privatePerson1person;//一本书属于一个人
publicBook1(String title,floatprice){//构造方法
this.setTitle(title);
this.setPrice(price);
}
publicString getTitle() {
returntitle;
}
publicvoidsetTitle(String title) {
this.title= title;
}
publicfloatgetPrice() {
returnprice;
}
publicvoidsetPrice(floatprice) {
this.price= price;
}
publicPerson1getPerson() {
returnperson;
}
publicvoidsetPerson(Person1person) {
this.person= person;
}
}
publicclassRefDemo06 {
publicstaticvoidmain(String[] args) {
Person1per =newPerson1("张三",30) ;//实例化对象
Person1cld =newPerson1("张四",10) ;//定义一个孩子
Book1bk =newBook1("Java基础",99.0f) ;//定义书
Book1bo =newBook1("十万个为什么",33.3f) ;
per.setBook(bk);//设置两个对象间的关系,一个人有一本书
bk.setPerson(per);//设置两个对象间的关系,一本书属于一个人
cld.setBook(bo);//设置对象间的关系,一个孩子有一本书
bo.setPerson(cld);//设置对象间关系,一本书属于一个孩子
per.setChild(cld);//设置对象间关系,一个人有一个孩子
+",年龄:"+ per.getAge() +",书名:"+ per.getBook().getTitle()
+",价格:"+ per.getBook().getPrice());//通过人名找到书
+",价格:"+ bk.getPrice() +",人名:"+ bk.getPerson().getName()
+",年龄:"+ bk.getPerson().getAge());//通过书名找到人
//通过人找到孩子,并找到孩子所拥有的书
+ per.getChild().getName() +",年龄:"+ per.getChild().getAge()
+",书名:"+per.getChild().getBook().getTitle() +",价格:"
+per.getChild().getBook().getPrice());
}
}
运行结果:
可以看到对应的关系也找了出来,对于代码的修改,在有标记的地方要主要修改。
总结
我们上面所有的应用范例,现在为止只是完成了一些比较细小的模型,但是这些模型都将成为日后JAVA EE开发中最重要的部分。希望可以反复理解引用传递的关系,并可以利用引用传递完成一些小的关系模型。
关爱IT人,关注挨踢栏
领取专属 10元无门槛券
私享最新 技术干货