博文主要介绍Java的基本数据类型种类和基本数据类型原理,帮助大家在面试中能够更好的应对面试中有关JDK源码的问题。
一、基本数据类型Java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量的初始化。基本类型,或者叫做内置类型,是Java中不同于类(Class)的特殊类型。它们是我们编程中使用最频繁的类型。Java基本类型共有八种,基本类型可以分为三类:
字符类型char
布尔类型boolean
数值类型byte
、short
、int
、long
、float
、double
基本数据类型有什么好处:我们都知道在Java语言中,new
一个对象是存储在堆里的,我们通过栈中的引用来使用这些对象;所以,对象本身来说是比较消耗资源的。对于经常用到的类型,如int等,如果我们每次使用这种变量的时候都需要new一个Java对象的话,就会比较笨重。所以,和C++一样,Java提供了基本数据类型,这种数据的变量不需要使用new创建,他们不会在堆上创建,而是直接在栈内存中存储,因此会更加高效。
Java中的整型主要包含byte
、short
、int
和long
这四种,表示的数字范围也是从小到大的,之所以表示范围不同主要和他们存储数据时所占的字节数有关。
整型中,每个类型都有一定的表示范围,但是,在程序中有些计算会导致超出表示范围,即溢出。如以下代码:这就是发生了溢出,溢出的时候并不会抛异常,也没有任何提示。所以,在程序中,使用同类型的数据进行运算的时候,一定要注意数据溢出的问题。
二、包装类型(引用类型)Java语言是一个面向对象的语言,但是Java中的基本数据类型却是不面向对象的,这在实际使用时存在很多的不便,为了解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八个和基本数据类型对应的类统称为包装类(Wrapper Class)。包装类均位于java.lang包,包装类和基本数据类型的对应关系如下表所示:
基本数据类型包装类byteBytebooleanBooleanshortShortcharCharacterintIntegerlongLongfloatFloatdoubleDouble为什么需要包装类
这个问题,其实前面已经有了答案,因为Java是一种面向对象语言,很多地方都需要使用对象而不是基本数据类型。比如,在集合类中,我们是无法将int 、double等类型放进去的。因为集合的容器要求元素是Object类型。为了让基本类型也具有对象的特征,就出现了包装类型,它相当于将基本类型“包装起来”,使得它具有了对象的性质,并为其添加了属性和方法,丰富基本类型的操作。
2.1 拆箱与装箱原理有了基本数据类型和包装类,肯定有些时候要在他们之间进行转换。比如把一个基本数据类型的int转换成一个包装类型的Integer对象。我们认为包装类是对基本类型的包装,所以,把基本数据类型转换成包装类的过程就是打包装,英文对应于boxing,中文翻译为装箱。反之,把包装类转换成基本数据类型的过程就是拆包装,英文对应于unboxing,中文翻译为拆箱。
/**
* 代码解读 1:
* 1.a1 = 200,底层会自动进行装箱操作
* 2.底层会new Integer(),重新分配内存地址
* 3.'=='比较的是引用地址(比较的是新内存地址)
*/
int a1 = 200;
int b1 = 200;
// 所以返回值:true
System.out.println(a1 == b1);
/**
* 1. int的缓存范围值是-128到127
* 2. 当a1=200时,会把int转为包装类(Integer),此时底层会new Integer(),重新分配内存地址
* 3. '=='比较的是引用地址,a1和a2都会进行装箱操作,已经new了新的地址,所有返回为false
*/
/**
* 代码解读 2:
* 1.a2 = 200时,底层会交易是否缓存范围之外,缓存之内外,会开辟新的存储空间
* 2.'=='比较的是引用地址(比较的是新内存地址)
*/
Integer a2 = 200;
Integer b2 = 200;
// 所以返回值:false
System.out.println(a2 == b2);
public static void main(String[] args) {
//基本数据类型的比较
int num1 = 10;
int num2 = 10;
System.out.println(num1 == num2); //true
//引用数据类型的比较
//String类(重写了equals方法)中==与equals的比较
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); //true,比较地址值:内容相同,因为常量池中只有一个“hello”,所以它们的地址值相同
System.out.println(s1.equals(s2));//true,比较内容:内容相同,因为常量池中只有一个“hello”,所以它们的地址值相同
System.out.println(s1.equals("hello")); //true
String s3 = new String("hello");
String s4 = new String("hello");
System.out.println(s3 == s4); //false,比较地址值:s3和s4在堆内存中的地址值不同
System.out.println(s3.equals(s4)); //true,比较内容:内容相同
//没有重写equals方法的类中==与equals的比较
People p1 = new People();
People p2 = new People();
People p = p2;
System.out.println(p1);//People@135fbaa4
System.out.println(p2);//People@45ee12a7
System.out.println(p); //People@45ee12a7
System.out.println(p1.equals(p2)); //false,p1和p2的地址值不同
System.out.println(p.equals(p2)); //true,p和p2的地址值相同
}
int的默认缓存范围值是-128到127之间,当变量值大于等于缓存范围值时,此时底层会new Integer(),重新分配内存地址。堆是用来存储程序中的一些对象,比如你用new关键字创建的对象,它就会被存储在堆内存中,但是这个对象在堆内存中的首地址会存储在栈中。在jvm中栈用来存储一些对象的引用、局部变量以及计算过程的中间数据,在方法退出后那么这些变量也会被销毁。它的存储比堆快得多,只比CPU里的寄存器慢。栈默认内存:1M。
博文参考《JDK源码分析》