「常见面试题」Java基础之基本数据类型&包装类型连环炮

这篇文章绝对干货!文章设计到的概念经常会被面试官拿来考察求职者的 Java 基础。

本篇采用大家比较喜欢的面试官问答的形式来展开。

基本数据类型

👨‍💻面试官 : Java 中有哪 8 种基本数据类型?

🙋 :Java 中有 8 种基本数据类型,分别为:

  1. 6 种数字类型 :byteshortintlongfloatdouble
  2. 1 种字符类型:char
  3. 1 种布尔型:boolean

👨‍💻面试官 : 它们的默认值和占用的空间大小知道不?

🙋 :这 8 种基本数据类型的默认值以及所占空间的大小如下:

基本类型位数字节默认值
int3240
short1620
long6480L
byte810
char162‘u0000’
float3240f
double6480d
boolean1false

另外,对于 boolean,官方文档未明确定义,它依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1 位,但是实际中会考虑计算机高效存储因素。

注意:

  1. Java 里使用 long 类型的数据一定要在数值后面加上 L,否则将作为整型解析:
  2. char a = 'h'char :单引号,String a = "hello" :双引号

包装类型

👨‍💻面试官 : 说说这 8 种基本数据类型对应的包装类型。

🙋 :这八种基本类型都有对应的包装类分别为:ByteShortIntegerLongFloatDoubleCharacterBoolean

👨‍💻面试官 :那基本类型和包装类型有啥区别不?

🙋 :包装类型不赋值就是 Null ,而基本类型有默认值且不是 Null

另外,这个问题建议还可以先从 JVM 层面来分析。

基本数据类型直接存放在 Java 虚拟机栈中的局部变量表中,而包装类型属于对象类型,我们知道对象实例都存在于堆中。相比于对象类型, 基本数据类型占用的空间非常小。

《深入理解 Java 虚拟机》 :局部变量表主要存放了编译期可知的基本数据类型**(boolean、byte、char、short、int、float、long、double)**、对象引用(reference 类型,它不同于对象本身,可能是一个指向对象起始地址的引用指针,也可能是指向一个代表对象的句柄或其他与此对象相关的位置)。

包装类型的常量池技术

👨‍💻面试官 : 包装类型的常量池技术了解么?

🙋 : Java 基本类型的包装类的大部分都实现了常量池技术。

Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在[0,127]范围的缓存数据,Boolean 直接返回 True Or False

Integer 缓存源码:

/**
*此方法将始终缓存-128 到 127(包括端点)范围内的值,并可以缓存此范围之外的其他值。
*/
public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
      return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static final Integer cache[];
}

Character 缓存源码:

public static Character valueOf(char c) {
    if (c <= 127) { // must cache
      return CharacterCache.cache[(int)c];
    }
    return new Character(c);
}

private static class CharacterCache {
    private CharacterCache(){}

    static final Character cache[] = new Character[127 + 1];
    static {
        for (int i = 0; i < cache.length; i++)
            cache[i] = new Character((char)i);
    }
}

Boolean 缓存源码:

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

如果超出对应范围仍然会去创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。

两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。

Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出 true
Float i11 = 333f;
Float i22 = 333f;
System.out.println(i11 == i22);// 输出 false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出 false

下面我们来看一下问题。下面的代码的输出结果是 true 还是 flase 呢?

Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);

Integer i1=40 这一行代码会发生拆箱,也就是说这行代码等价于 Integer i1=Integer.valueOf(40) 。因此,i1 直接使用的是常量池中的对象。而Integer i1 = new Integer(40) 会直接创建新的对象。

因此,答案是 false 。你答对了吗?

记住:所有整型包装类对象之间值的比较,全部使用 equals 方法比较

为什么要有包装类型?

👨‍💻面试官 : 为什么要有包装类型?

🙋

Java 本身就是一门 OOP(面向对象编程)语言,对象可以说是 Java 的灵魂。

除了定义一些常量和局部变量之外,我们在其他地方比如方法参数、对象属性中很少会使用基本类型来定义变量。

为什么呢?

我举个例子,假如你有一个对象中的属性使用了 基本类型,那这个属性就必然存在默认值了。这个逻辑不正确的!因为很多业务场景下,对象的某些属性没有赋值,我就希望它的值为 null。你给我默认赋个值,不是帮倒忙么?

另外,像泛型参数不能是基本类型。因为基本类型不是 Object 子类,应该用基本类型对应的包装类型代替。我们直接拿 JDK 中线程的代码举例。

Java 中的集合在定义类型的时候不能使用基本类型的。比如:

public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {
}

Map<Integer, Set<String>> map = new HashMap<>();

自动拆装箱

什么是自动拆装箱?原理?

👨‍💻面试官 : 什么是自动拆装箱?原理了解么?

🙋

基本类型和包装类型之间的互转。举例:

Integer i = 10;  //装箱
int n = i;   //拆箱

上面这两行代码对应的字节码为:

   L1
    LINENUMBER 8 L1
    ALOAD 0
    BIPUSH 10
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    PUTFIELD AutoBoxTest.i : Ljava/lang/Integer;
   L2
    LINENUMBER 9 L2
    ALOAD 0
    ALOAD 0
    GETFIELD AutoBoxTest.i : Ljava/lang/Integer;
    INVOKEVIRTUAL java/lang/Integer.intValue ()I
    PUTFIELD AutoBoxTest.n : I
    RETURN

从字节码中,我们发现装箱其实就是调用了 包装类的valueOf()方法,拆箱其实就是调用了 xxxValue()方法。

因此,

  • Integer i = 10 等价于 Integer i = Integer.valueOf(10)
  • int n = i 等价于 int n = i.intValue();

自动拆箱引发的 NPE 问题

👨‍💻面试官 : 自动拆箱可能会引发 NPE 问题,遇到过类似的场景么?

🙋

案例 1

在《阿里巴巴开发手册》上就有这样一条规定。

我们从上图可以看到,有一条是这样说的:“数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险”。

我们来模拟一个实际的案例:

public class AutoBoxTest {
    @Test
    void  should_Throw_NullPointerException(){
        long id = getNum();
    }
    public Long getNum(){
        return null;
    }
}

运行代码之后,果然出现了 NPE 的问题。

为什么会这样呢? 我们对 AutoBoxTest.class 进行反编译查看其字节码(我更推荐使用 IDEA 插件 jclasslib 来查看类的字节码)。

javap -c AutoBoxTest.class

反编译后得到的 should_Throw_NullPointerException() 方法的字节码如下:

0 aload_0
1 invokevirtual #2 <AutoBoxTest.getNum>
4 invokevirtual #3 <java/lang/Long.longValue>
7 lstore_1
8 return

我们可以发现自动拆箱 Long -> long 的过程,不过是调用了 longValue() 方法罢了!

public long longValue() {
   return value;
}

也就是说下面两行的代码实际是等价的:

long id = getNum();
long id = getNum().longValue();

因为,getNum()返回的值为 null ,一个 null 值调用方法,当然会有 NPE 的问题了。

案例 2

通过上面的分析之后,我来考了一个不论是平时开发还是面试中都经常会碰到的一个问题:“三目运算符使用不当会导致诡异的 NPE 异常”。

请你回答下面的代码会有 NPE 问题出现吗?如果有 NPE 问题出现的话,原因是什么呢?你会怎么分析呢?

public class Main {
    public static void main(String[] args) {
        Integer i = null;
        Boolean flag = false;
        System.out.println(flag ? 0 : i);
    }
}

答案是会有 NPE 问题出现的。

我们还是通过查看其字节码来搞懂背后的原理(这里借助了 IDEA 插件 jclasslib 来查看类字节码)。

从字节码中可以看出,22 行的位置发生了 拆箱操作

详细解释下就是:flag ? 0 : i 这行代码中,0 是基本数据类型 int,返回数据的时候 i 会被强制拆箱成 int 类型,由于 i 的值是 null,因此就抛出了 NPE 异常。

Integer i = null;
Boolean flag = false;
System.out.println(flag ? 0 : i);

如果,我们把代码中 flag 变量的值修改为 true 的话,就不会存在 NPE 问题了,因为会直接返回 0,不会进行拆箱操作。

我们在实际项目中应该避免这样的写法,正确 ✅ 修改之后的代码如下:

Integer i = null;
Boolean flag = false;
System.out.println(flag ? new Integer(0) : i);// 两者类型一致就不会有拆箱导致的 NPE 问题了

这个问题也在 《阿里巴巴开发手册》中 被提到过。

相关推荐
&lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:20px;color:#FF0000;&quot;&gt;本课程主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;span style=&quot;color:#FF0000;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;1. 包含:&lt;span style=&quot;color:#FFFF00;background-color:#FF0000;&quot;&gt;项目源码、&lt;/span&gt;&lt;span style=&quot;color:#FFFF00;background-color:#FF0000;&quot;&gt;项目文档、数据库脚本、软件工具&lt;/span&gt;等所有资料&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span style=&quot;color:#FF0000;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;2. 手把手的带你从零开始部署运行本套系统&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span style=&quot;color:#FF0000;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;3. 该项目附带的源码资料可作为毕设使用&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span style=&quot;color:#FF0000;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;4. 提供技术答疑和远程协助指导&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;br /&gt; &lt;/p&gt; &lt;p&gt; &lt;span style=&quot;font-size:18px;&quot;&gt;&lt;strong&gt;项目运行截图:&lt;/strong&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;1)系统登陆界面&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;img src=&quot;https://img-bss.csdn.net/202002241015433522.png&quot; alt=&quot;&quot; /&gt;&lt;br /&gt; &lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;2)学生模块&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;img src=&quot;https://img-bss.csdn.net/202002241015575966.png&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;3)教师模块&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;img src=&quot;https://img-bss.csdn.net/202002241016127898.png&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;4)系统管理员&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;img src=&quot;https://img-bss.csdn.net/202002241016281177.png&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;img src=&quot;https://img-bss.csdn.net/202002241016369884.png&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;br /&gt; &lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;更多Java毕设项目请关注我的毕设系列课程&nbsp;&lt;a href=&quot;https://edu.csdn.net/lecturer/2104&quot;&gt;https://edu.csdn.net/lecturer/2104&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/strong&gt; &lt;/p&gt; &lt;p&gt; &lt;strong&gt;&lt;span style=&quot;font-size:18px;&quot;&gt;&lt;br /&gt; &lt;/span&gt;&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt; 课程演示环境:Windows10&nbsp; &lt;/p&gt; &lt;p&gt; 需要学习&lt;span&gt;Ubuntus&lt;/span&gt;系统&lt;span&gt;YOLOv4-tiny&lt;/span&gt;的同学请前往《&lt;span&gt;YOLOv4-tiny&lt;/span&gt;目标检测实战:训练自己的数据集》 &lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&nbsp;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span style=&quot;color:#E53333;&quot;&gt;YOLOv4-tiny&lt;/span&gt;&lt;span style=&quot;color:#E53333;&quot;&gt;来了!速度大幅提升!&lt;/span&gt;&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&nbsp;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;YOLOv4-tiny&lt;/span&gt;在&lt;span&gt;COCO&lt;/span&gt;上的性能可达到:&lt;span&gt;40.2% AP50, 371 FPS (GTX 1080 Ti)&lt;/span&gt;。相较于&lt;span&gt;YOLOv3-tiny&lt;/span&gt;,&lt;span&gt;AP&lt;/span&gt;和&lt;span&gt;FPS&lt;/span&gt;的性能有巨大提升。并且,&lt;span&gt;YOLOv4-tiny&lt;/span&gt;的权重文件只有&lt;span&gt;23MB&lt;/span&gt;,适合在移动端、嵌入式设备、边缘计算设备上部署。&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&nbsp;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 本课程将手把手地教大家使用&lt;span&gt;labelImg&lt;/span&gt;标注和使用&lt;span&gt;YOLOv4-tiny&lt;/span&gt;训练自己的数据集。课程实战分为两个项目:单目标检测(足球目标检测)和多目标检测(足球和梅西同时检测)。&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&nbsp;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 本课程的&lt;span&gt;YOLOv4-tiny&lt;/span&gt;使用&lt;span&gt;AlexAB/darknet&lt;/span&gt;,在&lt;span&gt;Windows10&lt;/span&gt;系统上做项目演示。包括:&lt;span&gt;YOLOv4-tiny&lt;/span&gt;的网络结构、安装&lt;span&gt;YOLOv4-tiny&lt;/span&gt;、标注自己的数据集、整理自己的数据集、修改配置文件、训练自己的数据集、测试训练出的网络模、性能统计&lt;span&gt;(mAP&lt;/span&gt;计算&lt;span&gt;)&lt;/span&gt;和先验框聚类分析。 &lt;span&gt;&nbsp;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&nbsp;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 除本课程《&lt;span&gt;Windows&lt;/span&gt;版&lt;span&gt;YOLOv4-tiny&lt;/span&gt;目标检测实战:训练自己的数据集》外,本人推出了有关&lt;span&gt;YOLOv4&lt;/span&gt;目标检测的系列课程。请持续关注该系列的其它视频课程,包括:&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 《&lt;span&gt;Windows&lt;/span&gt;版&lt;span&gt;YOLOv4&lt;/span&gt;目标检测实战:训练自己的数据集》&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 《&lt;span&gt;Windows&lt;/span&gt;版&lt;span&gt;YOLOv4&lt;/span&gt;目标检测实战:人脸口罩佩戴识别》&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 《&lt;span&gt;Windows&lt;/span&gt;版&lt;span&gt;YOLOv4&lt;/span&gt;目标检测实战:中国交通标志识别》&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; 《&lt;span&gt;Windows&lt;/span&gt;版&lt;span&gt;YOLOv4&lt;/span&gt;目标检测:原理与源码解析》&lt;span&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&nbsp;&lt;img alt=&quot;&quot; src=&quot;https://img-bss.csdnimg.cn/202007061503586145.jpg&quot; /&gt;&lt;/span&gt; &lt;/p&gt; &lt;p&gt; &lt;span&gt;&lt;img alt=&quot;&quot; src=&quot;https://img-bss.csdnimg.cn/202007061504169339.jpg&quot; /&gt;&lt;br /&gt; &lt;/span&gt; &lt;/p&gt;
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值