Java基本数据类型与包装类的区别(栈、堆、常量池)
基本数据类型
基本数据类型(原始数据类型):包括八种基本数据类型:
基本数据类型(全部小写) | 取值范围 | 所占字节长度 |
---|---|---|
boolean | true/false | 理论上占用1bit,1/8字节,实际处理按1byte处理 |
byte | -128~127 | 1字节 |
short | -32768~32757 | 2字节 |
int | -21474836482147483647(-2^312^31-1) | 4字节 |
long | -263~263-1(很大就对了) | 8字节 |
float | 4字节 | |
long | 8字节 | |
char | 采用Unicode编码,表示范围\u0000~\uFFFF | 2字节 |
数据过大时,可以采用BigInteger(大整型)和BigDecimal(大浮点型)
包装类
基本类型的缺陷:Java的八种基本类型都有包装类。Java中的基本类型不是面向对象的,它们只是纯粹的数据,除了数值本身的信息之外,基本类型数据不带有其他信息或者可操作方法。
Java为什么有包装类
java中的数据类型int,double等不是对象,无法通过向上转型获取到Object提供的方法,而像String却可以,只因为String是一个对象而不是一个类型。基本数据类型由于这样的特性,导致无法参与转型,泛型,反射等过程。为了弥补这个缺陷,java提供了包装类。
即包装类是将基本数据类型及对基本类型的相关操作包装起来,形成一个类,使之能够想对象一样操作,称之为包装类。
**八种包装类(全部大写):**Boolean,Byte,Short,Integer,Long,Character,Float,Double
栈
栈的容量小但读取速度快。栈中存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中
堆
存放用new产生的数据 ,即对象本身。而操作对象的引用,放在栈中
基本类型的包装类和字符串有两种创建方式:
- 常量式(字面式)赋值创建,放在栈内存(将被常量化)
- Integer a = 10;
- String b = “abc”;
- new对象进行创建,放在堆内存(不会常量化)
- Integer c = new Integer(10);
- String d = new String(“abc”);
- 这两种创建方式导致创建的对象存放的位置不同
- 栈内存读取速度快但容量小
- 堆内存读取速度慢但容量大
常量池
- Java为很多基本类型的包装类/字符串都建立常量池
- 常量池:相同的值只存储一份,节省内存,共享访问
- 有常量池的类包括:Boolean,Byte,Short,Integer,Long,Character,String
- 注意:Float和Double没有常量池
包装类常量池的范围:
- Boolean,Byte,Short,Integer,Long,Character,Float,Double
- Boolean:true,false
- Character:0-127
- Byte,Short,Int,Long:-128-127
- **Float,Double:**没有缓存(常量池)
- Java为常量字符串都建立常量池缓存机制
- 在常量池中的这些字符串不会被垃圾收集器回收
一些小示例帮助理解
基本类型:
int i1 = 10;
Integer i2 = 10;//自动装箱
System.out.println(i1 == i2);//true
//自动拆箱 基本类型和包装类进行比较,包装类自动拆箱
Integer i3 = new Integer(10);
System.out.println(i1 == i3);//true
//自动拆箱 基本类型和包装类进行比较,包装类自动拆箱
System.out.println(i2 == i3);//false
//两个对象比较,比较其地址
//i2是常量,放在栈内存常量池中,i3是new出的对象,放在堆内存中
Integer i4 = new Integer(5);
Integer i5 = new Integer(5);
System.out.println(i1 == (i4 + i5));//true
System.out.println(i2 == (i4 + i5));//true
System.out.println(i3 == (i4 + i5));//true
//i4+i5操作会使得i4、i5自动拆箱为基本类型并运算得到10
//基础类型10和对象比较,将会使对象自动拆箱,做基本类型比较
字符串
String s0="abcdef";
String s1="abc";
String s2="abc";
String s3=new String("abc");
String s4=new String("abc");
System.out.println(s1==s2);//true 常量池
System.out.println(s1==s3);//false 一个栈内存,一个堆内存
System.out.println(s3==s4);//false 两个都是堆内存
String s5=s1+"def";//涉及到变量,故编译器不优化
String s6="abc"+"def";//都是常量 编译器会自动优化成abcdef
String s7="abc"+new String("def");//涉及到new对象,编译器不优化
System.out.println(s5==s6);//false
System.out.println(s5==s7);//false
System.out.println(s6==s7);//false
System.out.println(s0==s6);//true