大厂最爱问的 Java 基础面试题精选
作者:白色蜗牛
公众号:蜗牛互联网
前言
如果你是 Java 后端方向,Java 基础的知识就必须要相当熟悉。
蜗牛也做过面试官,本篇文章就从面试官的角度上,精选出 Java 基础相关的题目,我会给出参考答案,也会指明考察点,欢迎大家一起互动交流。
题目
1、什么是 JDK?你常用的版本是哪个?为什么用这个版本?
【考察点】
对 Java 开发工具的理解,以及技术选型方面的思考
【参考答案】
JDK 全称 Java Development ToolKit,直译一下就是 Java 语言开发工具包。
JDK 包含了 开发者工具比如 javac 用来编译 java 源码,jar 用来打包,还有一系列其他工具。此外,还包含了 JRE(Java Runtime Environment),也就是 Java 应用程序的运行环境,它除了运行程序的 java 指令外,还有类库以及执行 Java 应用程序的 JVM(Java 虚拟机)。
我常用的版本是 JDK8。一方面是这个版本已经比较稳定,另一方面,这个版本使用非常普遍,出了问题,很容易在网上找到答案。
2、一个Java程序从编码到运行,这中间发生了什么?
【考察点】
对 Java 程序运行原理的理解
【参考答案】
- 首先编程之后得到 .java 后缀的源代码文件。
- 用 JDK 中的 javac 命令将 Java 源代码进行编译,生成 Java 字节码,也就是 class 文件。
- 用 JRE 的 java 命令执行 class 文件时,Java 字节码会被传输到 JVM(Java 虚拟机),JVM 会合并字节码以及 JRE 中的库文件一起执行,输出特定硬件平台的机器码,或者说指令集。
- 机器码被底层物理硬件平台执行。
3、一个极简可运行的 Java 程序,它的代码有哪些要素?
【考察点】
对 Java 编码规范的理解
【参考答案】
- 类类型
- 类名
- 访问修饰符
- 成对的花括号
- main 方法
- 执行语句
4、Java 基本类型里的布尔类型占用多大的内存?
【考察点】
对 Java 基本数据类型的理解
【参考答案】
1 字节或 4 字节。
布尔类型表达是或者否,只有 true 和 flase 两个值,用关键字 boolean 表示,但 JVM 没有针对 boolean 的字节码指令,因此在虚拟机规范里,boolean 类型在编译后会被 int 代替,占用 4 个字节,如果是 boolean 数组,会被编译成 byte 数组类型,每个 boolean 数组元素占 1 个字节。实际情况就取决于各厂商发布的 JVM 实现了。
5、& 和 && 有什么区别?
【考察点】
对 Java 基本类型运算的理解
【参考答案】
&&:逻辑与运算符。当运算符左右两边的表达式都为 true,才返回 true。同时具有短路性,如果第一个表达式为 false,则直接返回 false。
&:既能当做逻辑与运算符,也能当做按位与运算符。
逻辑与运算符:& 在用于逻辑与时,和 && 的区别是不具有短路性。所以通常使用逻辑与运算符都会使用 &&,而 & 更多的适用于位运算。
按位与运算符:用于二进制的计算,只有对应的两个二进位均为1时,结果位才为1 ,否则为0。
6、以下代码为什么输出的不是 129?
int highIntValue = 129; byte lowByteValue = (byte)highIntValue; System.out.println(lowByteValue);
【考察点】
考察对计算机原码、反码和补码的理解
【参考答案】
这里会输出 -127,而不是 129。
在上面代码中,我们知道,int 类型数据是 32位,byte 类型数据为 8 位,Java 把 int 类型数据转成 byte 类型数据时,实质上是截取 int 后 8 位存到 byte 中。
int 类型的 129 三码(原码、反码和补码)一致,都为:0000 0000 0000 0000 0000 0000 1000 0001。计算机中存的是补码。
从 int 转换 byte,截取后 8 位为:1000 0001。得到的数据为依然是补码。
负数补码转原码的公式:
- 负数原码=(补码-1)&&数值位取反
我们按照公式,会发现其原码为:补码(1000 0001)–> 反码(1000 0000)–> 原码(1111 1111)。即 1111 1111 就是 (byte)highIntValue 的结果。
转换成十进制就是 lowByteValue=-(64+32+16+8+4+2+1)=-127。
7、new String("xxx"); 这行代码会产生几个对象?
【考察点】
考察对 Java 字符串存储机制的理解
【参考答案】
一个或两个。如果常量池中原来没有 xxx,就是两个。如果有就是一个。
String 是不可变类,Java 会分配一块常量池。通过以下代码解释下常量池的使用。
String str1 = "蜗牛666"; String str2 = "蜗牛666"; String newStr1 = new String("蜗牛666"); String newStr2 = new String("蜗牛666");
str1 这个变量接收了一个常量,于是存储到常量池中,执行到 str2 的赋值语句时,发现已经有相同的常量了,于是 str2 也指向了 str1 刚才那块内存空间。
newStr1 和 newStr2 是通过 ` new ` 语法创建的对象,在创建的过程中,Java 会先去常量池中查找是否已有 蜗牛666 对象,如果没有则在常量池中创建一个 蜗牛666 对象,然后在堆中创建一个 蜗牛666 的拷贝对象。
8、Java 的封装特性都体现在哪些地方?
【考察点】
考察对 Java 面向对象的基础知识。
【参考答案】
- 通过包(package)的方式,把一个模块封装到一起,并由几个接口开放给使用方。使用方只能看到接口信息,而看不到接口实现。
- 通过访问权限控制的方式,实现信息隐藏。
- 通过 getter 和 setter 方法,实现了对类成员有条件的读取和修改。
9、谈谈你对双亲委派模式的理解?
【考察点】
考察对 Java 类加载机制的理解。
【参考答案】
双亲委派模式要求除了顶层的引导类加载器外,其余的类加载器都应当有自己的父类加载器。
双亲委派的工作原理是,如果一个类收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,一次递归,请求最终将到达顶层的引导类加载器。
如果父类加载器可以完成类加载任务,就成功返回,如果父类加载器无法完成此加载任务,子加载器才会尝试自己去加载。
你会发现,Java 类随着它的类加载器具备了带有优先级的层次关系,通过这种层级关系,可以避免类的重复加载,当父类已经加载了该类,就没必要子加载器再加载一次。
因此像 java.lang.String 这种 Java 核心 API,即便你同名,JVM 也会优先加载 rt.jar 里的,因为引导类加载器是最顶级的加载器。这样也避免了 Java 核心 API 被随意替换,保证了安全。
后记
很多问题看似简短,背后能说道的东西其实很多,这就需要日积月累的沉淀,而非一朝一夕之功。面试题精选系列每一篇的题目不会超过 10 个,为的是读者朋友可以很好的消化内容,同时也能够深入了解相关的知识,希望对读者的面试能有帮助!