引用传递--栈区与堆内存(原理)

我们先看一个例子,简单版图书管理系统

public class Book {
    private String name;
    private String isbn;
    private double price;
    private int count;    //当前图书的数量
    private boolean borrow;

    public Book(){}
    public Book(String name){
        this.setName(name);
    }
    public Book(String name,String isbn,double price,int count){
        setName(name);
        setIsbn(isbn);
        setPrice(price);
        setCount(count);
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getIsbn() {
        return isbn;
    }
    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        if(count<0){
            count=0;
        }else {
            this.count = count;
        }
    }
    public boolean isIsborrow() {
        return borrow;
    }
    public void setIsborrow(boolean isborrow) {
        this.borrow = isborrow;
    }
}
public class BookBiz {
    //book要销售的书籍对象
    public int sellBook(Book book){
        if(!(book.getCount()>1)){
            return -1;
        }
        book.setCount(book.getCount()-1);
        return 1;
    }
}
public class BookTest {
    public static void main(String[] args){
        Book book=new Book("当年离骚","00-98",32,5);
        //实例化图书业务对象
        BookBiz bookbiz=new BookBiz();
        bookbiz.sellBook(book);
        System.out.println("库存量"+book.getCount());
    }
}

老九学堂笔记:

我们写道:

Book book=new Book("当年离骚","00-98",32,5);

 BookBiz bookbiz=new BookBiz();

bookbiz.sellBook(book);   时发生了什么?

main 方法的栈区 JVM的堆内存 哈希码内存地址
book:15db9742

当年离骚

00-98

32

5

15db9742
bookBiz:6d06d69c

相关属性

sellBook(Book book)

6d06d69c
sellBook的栈区

sellBook(Book book){

         book.coun--;

}

 

sellBook(book:15db9742){};

引用传递:参数部分传的是book这个对象在栈区中存的地址,根据这个地址可以找到堆内存里对应的内容,并对book.count这个值(5)进行操作(减1)。

 BookBiz bookbiz=new BookBiz();

public int sellBook(Book book){

          book.count--;

}

这个让我不自觉就想到了C语言中的指针。bookbiz在栈区中存了BookBiz的地址,传bookbiz进去时,实际上传的就是BookBiz的地址。然后对地址找到的内容进行相应的操作。

注意:1、对象不是引用变量。

                除了8中基本类型以外剩下的都是引用类型,Java 提供两种不同的类型:引用类型和原始类型。

                java中引用类型的变量和对象的区别 :

                对象是按照“类”这个模板建立的,建立的位置则是内存。例如A是一个类。A X则是创建一个引用变量,X=NEW A()   则是在内存中建立一个对象(开辟了1片空间),对象的模板就是A(可以理解为在空间里复制了A类里的变量到空间里 去)。
此时就可以使用引用变量X去引用对象中的变量了

                简单来说:对象是我们的本体,而不是我们的名字。
 

           2、对象引用和实际内存可以理解成遥控器和电视的关系。

                 栈区里面存了一堆堆遥控器,堆内存里面存了好多液晶电视。

           3、修改时真正修改的是堆内存中的内容,而不是栈区中的内容。

现在举一个例子加深引用传递的理解:



public class test2 {
    public static void main(String[] args){
        Demo demo=new Demo();  //1
        Swap(demo);
        System.out.println(demo.attr1+"\t"+demo.attr2);
    }
    static class Demo{
        int attr1=10,attr2=20;
    }
    public static void Swap(Demo demo){
        demo=new Demo();       //2
        int temp=demo.attr1;
        demo.attr1=demo.attr2;
        demo.attr2=temp;
    }
}

在这个例子中,输出的两个值为什么不是交换后的值呢?

就是因为Swap方法里面写了一句,demo=new Demo();

分析:主方法里的Demo demo=new Demo();从右往左念,首先在堆内存中申请了一块空间,并有了一个地址,我们叫它A

然后,在栈区有了一个变量demo存储了A这个地址。

下来进行到Swap(demo)这一步(进入方法):demo=new Demo()意味着堆内存中新开辟了一块内存空间,并有了一个地址,我们叫它B。那么现在栈区中的demo变量中存的是新地址B,覆盖了原来存的地址A,接下来交换的过程,实际上是在对“由B地址找到的堆内存空间进行了操作”,也就是说A地址所对应的堆内存空间是没有被操作的。

而后来打印的时候,打印的是A地址对应的变量值。所以不是交换后的结果。

猜你喜欢

转载自blog.csdn.net/miamia8989/article/details/84642444
今日推荐