首先我们来看下面一个题
如下代码运行结果是什么?
Character c1=134;
Character c2=134;
Character c3=13;
Character c4=13;
System.out.println("c1==c2"+(c1==c2));
System.out.println("c3==c4"+(c3==c4));
程序运行的结果为:
c1==c2false
c3==c4true
为什么会得到这个结果呢?我们得从常量池说起。
1.什么是常量池?
Java内存大题可以分为堆、栈、常量池、方法区。它们的基本区别如下图:
栈 stack |
存取速度快 数据可以共享 数据大小和生命周期必须确定,不够灵活
|
堆 heap |
运行时数据区 运行时动态分配内存 自动回收垃圾 存取速度较慢 |
方法区 method area |
用来存储类型信息
|
常量池 constant pool |
用来存储某类型的常量信息
|
由此可见,常量池是方法区的一部分,是内存的逻辑分区。使用如果两个变量使用常量池中的数据,那么两个变量指向常量池中相同的地址,否则他们都会新创建一个对象,指向不同的地址。看以下代码
Integer i1=10;
Integer i2=10;
Integer io1=new Integer(10);
Integer io2=new Integer(10);
System.out.println("i1==i2"+(i1==i2));
System.out.println("io1==io2"+(io1==io2));
i1、i2使用到了自动装箱,io1和io2则没有使用;i1 i2使用到常量池,io1、io2没有使用。因此程序的运行结果如下:
i1==i2true
io1==io2false
i1和i2的值都是10,所以指向常量池中相同的空间;因此i1==i2返回true;io1和io2使用new创建赋值,所以分别指向堆中不同的空间,因此io1==io2返回false;如下图:
注意:在自动装箱拆箱过程中,只有数值是byte范围内的时候,才使用到常量池,否则都是分配新的内存空间;
如以下代码:
Integer i3=1000;
Integer i4=1000;
Integer io3=new Integer(1000);
Integer io4=new Integer(1000);
System.out.println("i3==i4"+(i3==i4));
System.out.println("io3==io4"+(io3==io4));
1000早就超出了byte的范围,所以i3/i4是两个空间;