引用传递

引用传递时整个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 MessageDemo {
    public static void main(String[] args) {
        Message msg = new Message(30) ;
        fun(msg);
        System.out.println(msg.getNum());   //100
    }
    public static void fun(Message temp) {
        temp.setNum(100);
    }
}

内存分析图如下:


引用传递
范例一

范例二

public class MessageDemo2 {
    public static void main(String[] args) {
        String msg = "Hello";
        fun(msg);
        System.out.println(msg);    //Hello
    }

    public static void fun(String temp) {
        temp = "World" ;
    }
}

以上代码需要注意的是:String类对象的内容一旦声明,则不可改变;对象内容的改变实际是引用地址的改变。


引用传递
范例二

范例三

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

public class MessageDemo3 {
    public static void main(String[] args) {
        Message3 msg = new Message3("Hello");
        fun(msg);
        System.out.println(msg.getInfo());  //World
    }
    public static void fun(Message3 temp) {
        temp.setInfo("World");
    }
}

引用传递
范例3简单内存图

上面的描述并不严格,因为在程序里面,info也是一个String类的对象,下面是较清楚的内存分析图
引用传递
范例三严格内存图

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


实际应用

例:每一个人都有一辆汽车或没有汽车;要求可以通过面向对象的方式来描述。
范例:代码设计如下

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;    //表示属于人的车
    public Member(int mid , String name) {
        this.mid = mid;
        this.name = name;
    }
    public String getInfo() {
        return "人员编号:" + this.mid + ", 姓名:" + this.name;
    }
}

class Car {
    private Member member;  //车属于一个人
    private String pname;
    public Car(String pname) {
        this.pname = pname;
    }
    public String getInfo() {
        return "车的名字: " + this.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 "人员编号:" + this.mid + ", 姓名:" + this.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 "车的名字: " + this.pname;
    }
    public void setMember(Member member) {
        this.member = member;
    }
    public Member getMember() {
        return this.member;
    }
}

public class MemberCar{
    public static void main(String[] args){
        System.out.println("Hello World!");
    }
}

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

  • 第一步:根据定义的结构关系设置数据;
  • 第二步:根据定义的结构关系取出数据。
public class MemberCar{
    public static void main(String[] args){
        //第一步:设置数据
        Member m = new Member(1 , "张三");    //独立对象
        Car c = new Car("BMW");     //独立对象
        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 "人员编号:" + this.mid + ", 姓名:" + this.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;
    }
}

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

public class MemberCar{
    public static void main(String[] args){
        //第一步:设置数据
        Member m = new Member(1 , "张三");        //独立对象
        Member chd = new Member(2, "王五");       //一个孩子对象
        Car c = new Car("BMW");     //独立对象
        Car cc = new Car("Ferrari");    //一辆车
        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());  //代码链
    }
}