谈一谈Java的“引用”
- 首先说说Java的数据类型,毕竟学计算机的,一开始就要了解Java的两种数据类型:
声明一下,很多同学可能会和我一样,觉得类型和类是一个东西,其实还是有区别的,从上图就可以看出,类是类型中的一种(可能说的有点不准确),好了知道这个以后,我们再谈谈引用。
Java语言从C++发展而来,最重要的有一条是,Java**不支持指针类型,通过引用模型实现了指针的功能。**
那么指针的功能是什么呢?
指针指向了数据在内存中的地址,所以引用是不是也是指向了数据内存的地址呢?
只不过Java的引用更简洁(貌似python的好像也是,大家自己去摸索,不敢误导大家),我们知道C++的指针有两个很重要的操作:
*访问地址中的内容
&取该内容在内存中的地址
但是Java做了简单化,直接把这两个操作在我们对数据进行定义,访问的时候,就给自动操作了。
接下来看看看Java的引用机制对于不同类型的数据有啥区别:
- 基本类型(byte,short,int,long,float,double,char,boolean)的定义
int i=0;
定义的时候,堆内存中有给0这个数据开辟空间,至于这个空间的堆内存地址,Java底层肯定知道,但我们是不知道的,为什么不让我们知道,那就得问Java得创始人了,我们可以理解为此时内存中有一块专门空间,存储了0这个数据,然后Java给它取了个名字叫i。而且要知道一点,我们只能通过i来访问名字叫i的这块空间所存储的数据内容,不能访问这块空间的地址(想知道为啥,就得自己去问Java的创始人,我也不知道为啥)
int j=i
这个过程有没有分配空间呢?没有,Java只是给名字为i这块堆内存空间又取了个名字,叫j
j=2;
跟第一句的分析是一样的,不过现在Java把j这个名字给到了新的开辟空间,
那么此时我们看看堆内存中,知道,现在有两个空间,一个名字叫i,它存储了0这个数据,另一个空间叫j,它存储了2这个数据,而且i和j没有任何联系了
再看下面的语句
int i=0;
int j=i
i++;
那么问你j现在是多少?
很多同学可能会以为是1,为啥,因为会习惯性的认为名字i和j其实表示了同一块空间,现在对i表示的空间发生了数据变化,那么j是不是也变化了
但很遗憾,你没有理解到其实计算机的思维和我们大脑不太一样,所有的指令都必须现开辟控件存储,然后操作,操作的过程中,也是需要现存储,再接下来继续操作
比如I++,其实执行的是
i=i;
i=i+1
主要看i=i+1
i+1它的结果需不需要用东西来存储,如果你说不需要,那抱歉,建议你转行,Java会开辟一个新的空间,来存储结果1,然后呢再把i这个名字给到这个空间,现在清楚了,目前堆内存中也有两个空间,一个名字叫j,存储的内容是0,还有一个名字叫j,存储的内容是1
- 引用类型
int[] i={1,2,3,4,5};
int[] j=i;
j[0]=100
现在问你i的值是多少?
分析:int[] i={1,2,3,4,5}
熟悉C或C++的知道,数组名其实就是一个指针,指向了首地址
Java是怎么做的呢,它给开辟了两个空间,一个堆空间,存储了1,2,3,4,5,其实应该是5个连续仔一起的空间,然后一个栈空间,存储了堆空间的首地址,也就是1的空间地址,Java给这个栈空间起了一个名字叫i
int[] j=i
Java又分配了一个栈空间,给它起名字叫做j,这个栈空间存储了i里面存储的内容,也就是堆的首地址
j[0]=100
好了,类还有接口其实是一样的分析
下面说几个疑惑的点:
- 我们一开始就被灌输了Java是完全面向对象的,然后呢int i=0的时候,i是一个整数对象,但是int是类吗?我们很容易先入为主,以为int就是类,其实不对,他只是类型,而不是类,不信的同学可以去试试i.toString()会不会报错,因为Java中所有的类都是继承于Object,然后Object有两个方法,一个是toString,一个是equals
- String类型的困惑
String确实是类,你可以用String ss="1234"或者String ss=new String(“1234”),然后ss.toString()试一试,不过需要说明的是,因为字符串在程序设计中太重要了,所以Java就直接给封装好了,所以这让人们对他不是很了解。
但是有一点需要特别说明的是,尽管字符串是类,但它的实例化对象是不可变的,应该按照基本类型思路去分析才对,至于为什么,问Java创始人。
总结
- 我们可以看到基本数据类型比较小,在进行操作的时候,都是直接先开辟堆空间,然后把内容存储到堆空间,而引用数据类型比较大,在进行操作的时候,都是开辟栈空间,然后通过栈空间,对它所指向的堆空间进行操作,至于为什么,自己去问Java创始人。