本文共 1384 字,大约阅读时间需要 4 分钟。
引用类是java中一个很抽象的一个概念,很多人因为对于引用类基本都是实操,但是对于基础理论,底层原理都是一窍不通的。比如说,为什么明明我们都赋值了,但是出现程序错误?实例化是什么?实例化在jvm中是什么样一样的存在?接下来请看本文。
在说引用类之前,我们都知道java类型可以分成两大类型——值类型和引用类。值类型就是八种基本数据类型int,long等这些,而引用类就是以基本类型为基础进行延伸的——除了变量以外的所有类型称为引用类型。
下面我们看一个引用类型的例子
//另起一个class类名为Tepublic class Te { public String name; public int age;}public class six { public static void main(String[] args) { Te a = new Te();//Te实例化后对象传给a Te b = a;//Te建一个对象b去引用a的地址 a.name = "a"; b.name = "b"; System.out.println(a.name); a = null; System.out.println(a.name);}}
你们猜一下第一个输出的是什么? 是a还是b呢?如果选a的小伙伴,那就说明还没有值覆盖的概念,什么叫值覆盖呢?首先看下面这个图。
第一个输出:
我们都知道,name没有赋值时候是null,age是0。这两个都是Te类的两个公共属性值,这个就说明了只要实例化了Te类就可以调用Te的方法和域。Te的对象a和b引用均放在栈里,当Te实例化后放在堆中,属性值均放在堆中。
现在b获得了a的地址,当b.name赋值时,a.name也应该被改变。因为a和b都是引用同一个地址的属性值,而a本身是赋值给name的,当程序读到输出前b赋值给name,由于两个对象都是引用同一个地址的属性值,所以a的值会被b赋的值覆盖。
第二个输出
第二个相信很多人看了图后都知道输出什么了,是的程序报错。
如图
原因其实很简单,a本身是有一个指向new Te()的指针,现在a=null就意味着指针也就是引用的地址被置空,就没有了图中这根线,相当于断了,所以说输出a.name其实是不可能的。那么举一反三,猜想一下,输出b.name可能吗?答案,是完全没有影响的,还是能正常输出。
java中有一个拥有着引用类的值类型Integer,为什么叫引用类的值类型呢?首先Integer是由int类封装的承,但是与int类不同就是Integer是一种引用类,也叫复杂类型,r所以如果Integer没有设值,那就是null,int不能够new int,但是Integer可以new Intege。现在,Integer这么与众不同,在堆和栈是怎么一个位置安排呢?
如,Integer a= new Integer(15);
依然没有任何影响,很合理的一个引用类在堆中的创建,但是Integer赋值15是放在堆里还是栈里呢??
这里,需要把Integer类特殊化处理,他的本质是int封装过来的,所以赋值的时候是赋值给本身的,而不是引用地址的值。
所以可以说15值赋给本身的,所以值在栈中,而不是在堆中。
转载地址:http://ljtrn.baihongyu.com/