关键词:
你不知道的基本数据类型和包装类 + 面试题
基本数据类型
Java 基本数据按类型可以分为四大类:布尔型、整数型、浮点型、字符型,这四大类包含 8 种基本数据类型。
- 布尔型:boolean
- 整数型:byte、short、int、long
- 浮点型:float、double
- 字符型:char
8 种基本类型取值如下:
数据类型 代表含义 默认值 取值 包装类 boolean 布尔型 false 0(false) 到 1(true) Boolean byte 字节型 (byte)0 ﹣128 到 127 Byte char 字符型 'u0000'(空) 'u0000' 到 'uFFFF' Character short 短整数型 (short)0 -215215 到 215215-1 Short int 整数型 0 ﹣231231 到 231231-1 Integer long 长整数型 0L ﹣263263 到 263263-1 Long float 单浮点型 0.0f 1.4e-45 到 3.4e+38 Float double 双浮点型 0.0d 4.9e-324 到 1.798e+308 Double
除 char 的包装类 Character 和 int 的包装类 Integer 之外,其他基本数据类型的包装类只需要首字母大写即可。包装类的作用和特点,本文下半部分详细讲解。
我们可以在代码中,查看某种类型的取值范围,代码如下:
public static void main(String[] args)
// Byte 取值:-128 ~ 127
System.out.println(String.format("Byte 取值:%d ~ %d", Byte.MIN_VALUE, Byte.MAX_VALUE));
// Int 取值:-2147483648 ~ 2147483647
System.out.println(String.format("Int 取值:%d ~ %d", Integer.MIN_VALUE, Integer.MAX_VALUE));
包装类型
我们知道 8 种基本数据类型都有其对应的包装类,因为 Java 的设计思想是万物既对象,有很多时候我们需要以对象的形式操作某项功能,比如说获取哈希值(hashCode)或获取类(getClass)等。
那包装类特性有哪些?
1. 功能丰富
包装类本质上是一个对象,对象就包含有属性和方法,比如 hashCode、getClass 、max、min 等。
2. 可定义泛型类型参数
包装类可以定义泛型,而基本类型不行。
比如使用 Integer 定义泛型,代码:
List<Integer> list = new ArrayList<>();
如果使用 int 定义就会报错,代码:
List list = new ArrayList<>(); // 编译器代码报错
3. 序列化
因为包装类都实现了 Serializable 接口,所以包装类天然支持序列化和反序列化。比如 Integer 的类图如下:
4. 类型转换
包装类提供了类型转换的方法,可以很方便的实现类型之间的转换,比如 Integer 类型转换代码:
String age = "18";
int ageInt = Integer.parseInt(age) + 2;
// 输出结果:20
System.out.println(ageInt);
5. 高频区间的数据缓存
此特性为包装类很重要的用途之一,用于高频区间的数据缓存,以 Integer 为例来说,在数值区间为 -128~127 时,会直接复用已有对象,在这区间之外的数字才会在堆上产生。
我们使用 == 对 Integer 进行验证,代码如下:
public static void main(String[] args)
// Integer 高频区缓存范围 -128~127
Integer num1 = 127;
Integer num2 = 127;
// Integer 取值 127 == 结果为 true(值127 num1==num2 => true)
System.out.println("值127 num1==num2 => " + (num1 == num2));
Integer num3 = 128;
Integer num4 = 128;
// Integer 取值 128 == 结果为 false(值128 num3==num4 => false)
System.out.println("值128 num3==num4 => " + (num3 == num4));
从上面的代码很明显可以看出,Integer 为 127 时复用了已有对象,当值为 128 时,重新在堆上生成了新对象。
为什么会产生高频区域数据缓存?我们查看源码就能发现“线索”,源码版本 JDK8,源码如下:
public static Integer valueOf(int i)
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
由此可见,高频区域的数值会直接使用已有对象,非高频区域的数值会重新 new 一个新的对象。
各包装类高频区域的取值范围:
- Boolean:使用静态 final 定义,就会返回静态值
- Byte:缓存区 -128~127
- Short:缓存区 -128~127
- Character:缓存区 0~127
- Long:缓存区 -128~127
- Integer:缓存区 -128~127
包装类的注意事项
- int 的默认值是 0,而 Integer 的默认值是 null。
- 推荐所有包装类对象之间的值比较使用
equals()
方法,因为包装类的非高频区数据会在堆上产生,而高频区又会复用已有对象,这样会导致同样的代码,因为取值的不同,而产生两种截然不同的结果。代码示例:
public static void main(String[] args)
// Integer 高频区缓存范围 -128~127
Integer num1 = 127;
Integer num2 = 127;
// Integer 取值 127 == 结果为 true(值127 num1==num2 => true)
System.out.println("值127 num1==num2 => " + (num1 == num2));
Integer num3 = 128;
Integer num4 = 128;
// Integer 取值 128 == 结果为 false(值128 num3==num4 => false)
System.out.println("值128 num3==num4 => " + (num3 == num4));
// Integer 取值 128 equals 结果为 true(值128 num3.equals(num4) => true)
System.out.println("值128 num3.equals(num4) => " + num3.equals(num4));
- Float 和 Double 不会有缓存,其他包装类都有缓存。
- Integer 是唯一一个可以修改缓存范围的包装类,在 VM optons 加入参数:
-XX:AutoBoxCacheMax=666 即修改缓存最大值为
666
。
示例代码如下:
public static void main(String[] args)
Integer num1 = -128;
Integer num2 = -128;
System.out.println("值为-128 => " + (num1 == num2));
Integer num3 = 666;
Integer num4 = 666;
System.out.println("值为666 => " + (num3 == num4));
Integer num5 = 667;
Integer num6 = 667;
System.out.println("值为667 => " + (num5 == num6));
执行结果如下:
值为-128 => true
值为666 => true
值为667 => false
由此可见将 Integer 最大缓存修改为 666 之后,667 不会被缓存,而 -128~666 之间的数都被缓存了。
相关面试题
1. 以下 Integer 代码输出的结果是?
Integer age = 10;
Integer age2 = 10;
Integer age3 = 133;
Integer age4 = 133;
System.out.println((age == age2) + "," + (age3 == age4));
答:true,false
2. 以下 Double 代码输出的结果是?
Double num = 10d;
Double num2 = 10d;
Double num3 = 133d;
Double num4 = 133d;
System.out.println((num == num2) + "," + (num3 == num4));
答:false,false
3. 以下程序输出结果是?
int i = 100;
Integer j = new Integer(100);
System.out.println(i == j);
System.out.println(j.equals(i));
A:true,true
B:true,false
C:false,true
D:false,false
答:A
题目分析:有人认为这和 Integer 高速缓存有关系,但你发现把值改为 10000 结果也是 true,true
,这是因为 Integer 和 int 比较时,会自动拆箱为 int 相当于两个 int 比较,值一定是 true,true
。
4. 以下程序执行的结果是?
final int iMax = Integer.MAX_VALUE;
System.out.println(iMax + 1);
A:2147483648
B:-2147483648
C:程序报错
D:以上都不是
答:B
题目解析:这是因为整数在内存中使用的是补码的形式表示,最高位是符号位 0 表示正数,1 表示负数,当执行 +1 时,最高位就变成了 1,结果就成了 -2147483648。
5. 以下程序执行的结果是?
Set<Short> set = new HashSet<>();
for (short i = 0; i < 5; i++)
set.add(i);
set.remove(i - 1);
System.out.println(set.size());
A:1
B:0
C:5
D:以上都不是
答:5
题目解析:Short 类型 -1 之后转换成了 Int 类型,remove() 的时候在集合中找不到 Int 类型的数据,所以就没有删除任何元素,执行的结果就是 5。
6. short s=2;s=s+1;
会报错吗?short s=2;s+=1;
会报错吗?
答:s=s+1 会报错,s+=1 不会报错,因为 s=s+1 会导致 short 类型升级为 int 类型,所以会报错,而 s+=1 还是原来的 short 类型,所以不会报错。
7. float f=3.4;
会报错吗?为什么?
答:会报错,因为值 3.4 是 double 类型,float 类型级别小于 double 类型,所以会报错。如下图所示:
8. 为什么需要包装类?
答:需要包装类的原因有两个。
① Java 的设计思想是万物既对象,包装类体现了面向对象的设计理念;
② 包装类包含了很多属性和方法,比基本数据类型功能多,比如提供的获取哈希值(hashCode)或获取类(getClass)的方法等。
9. 基本类 int 和包装类 Integer,在 -128~127 之间都会复用已有的缓存对象,这种说法正确吗?
答:不正确,只有包装类高频区域数据才有缓存。
10. 包装类 Double 和 Integer 一样都有高频区域数据缓存,这种说法正确吗?
答:不正确,基本数据类型的包装类只有 Double 和 Float 没有高频区域的缓存。
11. 包装类的值比较要使用什么方法?
答:包装类因为有高频区域数据缓存,所以推荐使用 equals() 方法进行值比较。
12. 包装类有哪些功能?
答:包装类提供的功能有以下几个。
- 功能丰富:包装类包含了有 hashCode、getClass 、max、min 等方法;
- 可定义泛型类型参数:例如
List<Integer> list = new ArrayList<>();
; - 序列化:包装类实现了 Serializable 接口,所以包装类天然支持序列化和反序列化;
- 类型转换:包装类提供了方便的类型转换方法,比如 Integer 的 parseInt() 方法;
- 高频区域数据缓存:高频区域可使用已有的缓存对象。
详见正文“包装类型”部分内容。
13. 泛型可以为基本类型吗?为什么?
答:泛型不能使用基本数据类型。泛型在 JVM(Java虚拟机)编译的时候会类型檫除,比如代码 List<Integer> list
在 JVM 编译的时候会转换为 List list
,因为泛型是在 JDK 5 时提供的,而 JVM 的类型檫除是为了兼容以前代码的一个折中方案,类型檫除之后就变成了 Object,而 Object 不能存储基本数据类型,但可以使用基本数据类型对应的包装类,所以像 List<int> list
这样的代码是不被允许的,编译器阶段会检查报错,而 List<Integer> list
是被允许的。
14. 选择包装类还是基本类的原则有哪些?
答:我们知道正确的使用包装类,可以提供程序的执行效率,可以使用已有的缓存,一般情况下选择基本数据类型还是包装类原则有以下几个。
① 所有 POJO 类属性必须使用包装类;
② RPC 方法返回值和参数必须使用包装类;
③ 所有局部变量推荐使用基本数据类型。
15. 基本数据类型在 JVM 中一定存储在栈中吗?为什么?
答:基本数据类型不一定存储在栈中,因为基本类型的存储位置取决于声明的作用域,来看具体的解释。
- 当基本数据类型为局部变量的时候,比如在方法中声明的变量,则存放在方法栈中的,当方法结束系统会释放方法栈,在该方法中的变量也会随着栈的销毁而结束,这也是局部变量只能在方法中使用的原因;
- 当基本数据类型为全局变量的时候,比如类中的声明的变量,则存储在堆上,因为全局变量不会随着某个方法的执行结束而销毁。
16. 以下程序执行的结果是?
Integer i1 = new Integer(10);
Integer i2 = new Integer(10);
Integer i3 = Integer.valueOf(10);
Integer i4 = Integer.valueOf(10);
System.out.println(i1 == i2);
System.out.println(i2 == i3);
System.out.println(i3 == i4);
A:false,false,false
B:false,false,true
C:false,true,true
D:true,false,false
答:B
题目解析:new Integer(10) 每次都会创建一个新对象,Integer.valueOf(10) 则会使用缓存池中的对象。
17. 3*0.1==0.3 返回值是多少?
答:返回值为:false。
题目解析:因为有些浮点数不能完全精确的表示出来,如下代码:
System.out.println(3 * 0.1);
返回的结果是:0.30000000000000004。
如果喜欢的话,欢迎关注我的公众号!回复关键字“Java”,将会有大礼相送!
可能你不知道的,关于自动装箱和自动拆箱(代码片段)
包装类我们知道,Java中包含了8种基本数据类型:整数类型:byte、short、int、long字符类型:char浮点类型:float、double布尔类型:boolean这8种基本数据类型的变量不需要使用new来创建,它们不会在堆上创建,而是直接在栈内存中存... 查看详情
java中的基本数据类型和包装类型的这些知识,你都知道吗?(代码片段)
Java中的基本数据类型和包装类型Java中的基本数据按类型可以分为四大类:布尔型、整数型、浮点型、字符型;这四大类包含8种基本数据类型。布尔型:boolean整数型:byte、short、int、long浮点型:float、double字符型:char这8种基本... 查看详情
1.31号java复习题目——java的基本数据类型和包装类(面试题刷题)(代码片段)
1.以下Integer代码输出的结果是?Integerage=10;Integerage2=10;Integerage3=133;Integerage4=133;System.out.println((age==age2)+","+(age3==age4));答:true,false2.以下Double代码输出的结果是?Doublenum=10d;Doublenum2=10d;Doublenum3=133d;Doublenum4=133d;System.out.println((num==num2)... 查看详情
三元运算符和包装类的一些细节(面试题)(代码片段)
示例如下:boolean?Objecto1:Objecto2编译时就必须保证o1和o2为同一类型变量Objecto=true?newInteger(1):newDouble(2.0);System.out.println(o);//1.0先把后边两个对象转换为统一包装类型Double后,然后赋值给变量o,此时o为Double类型的变量,所以输出结果为1.0. 查看详情
java实习生面试题整理(代码片段)
一、数据类型包装类型八个基本类型:boolean/1byte/8char/16short/16int/32float/32long/64double/64基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。?12Integerx=2; //装箱inty=x;&nbs... 查看详情
java包装类(代码片段)
一.什么是包装类 Java中的基本数据类型没有方法和属性,而包装类就是为了让这些拥有方法和属性,实现对象化交互。 数值型包装类都继承至Number,而字符型和布尔型继承至Object。二.基本数据和包装类之间的转换 ... 查看详情
基本类型和包装类(代码片段)
包装类的产生就是为了解决基本数据类型没有属性,方法,不能对象化交互的问题基本数据类型和包装类之间的对应关系如下:基本类型——包装类byte——Byteshort——Shortint——Integerlong——Longfloat——Floatdouble——Doublechar——C... 查看详情
近7000字长文详细讲解java包装类,面试稳了(代码片段)
零基础学习之Java包装类概述基本介绍包装类的使用装箱介绍代码示例拆箱介绍代码示例包装类常见的API基本数据类型和字符串之间的转换数据类型的最大值和最小值转大小写转进制包装类对象的缓存问题介绍面试常考常见笔试... 查看详情
java——10个关于java数据类型的面试题(代码片段)
文章目录:1.Java的基本数据类型(及包装类型)都有哪些各占几个字节?2.String是基本数据类型吗?3.String类可以被继承吗?4.Strings="Hello";s=s+"world!";这两行代码执行后,原始的String... 查看详情
java进阶包装类(代码片段)
文章目录1包装类与基本数据类2包装类的常用方法3基本数据类型和包装类之间的转换4基本数据类型与字符串之间的转换5默认值6对象常量池1包装类与基本数据类基本类型对应的包装类byteByteshortShortintIntegerlongLongfloatFloatdoubleDoublec... 查看详情
拆箱和装箱(有了基本数据类型为什么还需要包装类)(代码片段)
1,什么是基本数据类型java中提供了八个基本的数据类项:int,byte,short,long,float,double,boolean,char*String不是基本的数据类型每个基本的数据类型都会有一个对应得包装类int---Integer2,装箱和拆箱装箱,哪基本数据类项转换成对应的... 查看详情
包装类(代码片段)
所为的包装类值得是将基本数据类型封装在一个类 这个时候的MyInt实际上是Int类型的包装类,利用MyInt可以实现基本数据类型转换为对象范例: 结论:将基本数据类型包装为一个类对象的本质在于方便进行Object进行接收... 查看详情
java基本类型和包装类什么情况下判断相等(“==“或“equals“)?(代码片段)
[1]先讨论一个面试题inta=1;Integerb=1;Integerc=newInteger(1);Integerd=Integer.valueOf(1);inte=d;intf=d.intValue(); 请问以下式子的值?为什么?a==b//truea==c//trueb= 查看详情
常用类(代码片段)
1.包装类把八大基本数据类型封装到一个类中,并提供属性和方法,更方便的操作基本数据类型。包装类的出现并不是用于取代基本数据类型,也取代不了。包装类位于java.lang包中。Number 类Number数值类型是byte、double、float、i... 查看详情
有了基本数据类型,为什么还需要包装类型(代码片段)
一:java数据类型 在java中有八种基本数据类型对应每种基本类型又有八种包装类型: 基本类型:boolean,char,int,byte,short,long,float,double 包装器类型:Boolean,Character,Integer,Byte,Short,Long,Float,Double 从上... 查看详情
java面试题总结|java基础部分(持续更新)(代码片段)
...和面向过程简述自动装箱拆箱Java代码块执行顺序java中的基本数据类型对应的字节数包装类型和基本数据类型的场景java中的关键字分类final关键字static关键字字符串比较问题多态简述throw与throws的区别java的异常throw和throws的区别tr... 查看详情
java面试题(代码片段)
...父类引用指向子类对象,并且有继承,有重写。String是最基本的数据类型吗?String是类类型,不是基本类型。基本类型有八种:整型(4种)字符型(1种)浮点型(2种)布尔型(1种)int和Integer有什么区别?int是基本类型32位长度... 查看详情
基础面试题:==与equals详解(代码片段)
java中的数据类型分为:基本数据类型和引用数据类型基础类型4种整数类型:int、long、byte、short2种浮点数类型:float、double1种字符类型:char1种布尔类型:boolean引用数据类型类接口数组对于基本类型来说,==比较的是值是否相等... 查看详情