以下是一篇关于互联网大厂 Java 求职者面试的文章:
《互联网大厂 Java 求职者面试三轮问答及答案》
第一轮: 面试官:请你简述一下 Java 的基本数据类型有哪些? 王铁牛:有 byte、short、int、long、float、double、char、boolean 这几种。 面试官:不错,那你说说这些数据类型的默认值分别是多少? 王铁牛:byte 是 0,short 是 0,int 是 0,long 是 0L,float 是 0.0f,double 是 0.0d,char 是 '\u0000',boolean 是 false。 面试官:回答得很准确,那你再讲讲 Java 中的自动装箱和拆箱是怎么回事? 王铁牛:自动装箱就是把基本数据类型自动转换成对应的包装类对象,拆箱则是把包装类对象自动转换成基本数据类型。
第二轮: 面试官:在 Java 中,多线程有哪些实现方式? 王铁牛:有继承 Thread 类和实现 Runnable 接口这两种方式。 面试官:很好,那你说说这两种方式的区别是什么? 王铁牛:继承 Thread 类方式比较简单,但如果要继承多个类就不行了;实现 Runnable 接口方式可以避免单继承的局限性,更适合多个线程共享资源的情况。 面试官:那你再说说线程的生命周期有哪些状态? 王铁牛:有新建、就绪、运行、阻塞和死亡这几种状态。
第三轮: 面试官:谈谈你对 HashMap 的理解,它的底层原理是什么? 王铁牛:HashMap 是基于哈希表实现的,通过 key 的哈希值来确定存储位置。 面试官:那在 HashMap 中,如果发生哈希冲突怎么办? 王铁牛:会使用链表来解决冲突,当链表长度超过阈值时会转换成红黑树。 面试官:最后,你说说 HashMap 的线程安全性问题以及如何解决? 王铁牛:HashMap 不是线程安全的,在多线程环境下可能会出现数据丢失等问题。可以使用 ConcurrentHashMap 来解决,它是线程安全的。
面试官:今天的面试就到这里,你可以先回去等通知,我们会尽快给你回复。
答案:
- Java 的基本数据类型及默认值:
- byte:字节型,占 1 个字节,默认值为 0。用于表示整数,范围是 -128 到 127。
- short:短整型,占 2 个字节,默认值为 0。用于表示整数,范围是 -32768 到 32767。
- int:整型,占 4 个字节,默认值为 0。是最常用的整数类型,范围是 -2147483648 到 2147483647。
- long:长整型,占 8 个字节,默认值为 0L。用于表示较大的整数,范围是 -9223372036854775808 到 9223372036854775807。
- float:单精度浮点型,占 4 个字节,默认值为 0.0f。用于表示小数,精度较低。
- double:双精度浮点型,占 8 个字节,默认值为 0.0d。用于表示小数,精度较高。
- char:字符型,占 2 个字节,默认值为 '\u0000'。用于表示单个字符。
- boolean:布尔型,占 1 位,默认值为 false。用于表示真或假。
- Java 中多线程的实现方式及区别:
- 继承 Thread 类:通过继承 Thread 类来创建线程,重写 run() 方法来定义线程的执行逻辑。这种方式比较简单,但如果要继承多个类就不行了,因为 Java 不支持多继承。
- 实现 Runnable 接口:定义一个实现 Runnable 接口的类,重写 run() 方法,然后创建 Thread 对象并将 Runnable 对象作为参数传递给 Thread 的构造函数。这种方式可以避免单继承的局限性,更适合多个线程共享资源的情况。
- 线程的生命周期状态:
- 新建:通过 new 关键字创建线程对象,但还未调用 start() 方法启动线程。
- 就绪:线程对象创建后,调用 start() 方法,线程进入就绪状态,等待 CPU 调度。
- 运行:线程获得 CPU 时间片,开始执行 run() 方法中的代码。
- 阻塞:线程在执行过程中,由于等待某个条件满足(如等待 I/O 操作完成、锁等待等)而暂停执行,进入阻塞状态。
- 死亡:线程执行完 run() 方法或因异常而终止,线程进入死亡状态。
- HashMap 的底层原理:
- HashMap 是基于哈希表实现的,通过 key 的哈希值来确定存储位置。哈希表是一种数据结构,它使用数组和链表(或红黑树)来存储键值对。
- 当向 HashMap 中插入元素时,首先根据 key 的哈希值计算出存储位置,如果该位置为空,则直接将元素插入;如果该位置已存在元素,则通过比较 key 的哈希值和 equals() 方法来确定是否为相同的 key,如果是相同的 key,则更新 value;如果是不同的 key,则将新元素插入到链表或红黑树中。
- HashMap 中哈希冲突的解决方式:
- 在 HashMap 中,如果发生哈希冲突,会使用链表来解决冲突。当链表长度超过阈值(默认是 8)时,会将链表转换成红黑树,以提高查询效率。
- HashMap 的线程安全性问题及解决方法:
- HashMap 不是线程安全的,在多线程环境下可能会出现数据丢失等问题。例如,多个线程同时对 HashMap 进行插入、删除等操作时,可能会导致数据结构的混乱。
- 可以使用 ConcurrentHashMap 来解决线程安全问题。ConcurrentHashMap 是 Java 提供的线程安全的哈希表实现,它采用了分段锁的机制,将哈希表分成多个段,每个段都有自己的锁,从而可以同时支持多个线程对不同段的操作,提高了并发性能。