我们先看一个例子,简单版图书管理系统
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地址对应的变量值。所以不是交换后的结果。