Java面试宝典:基础一
⚙️ 1. Java跨平台原理(字节码文件与JVM)
- 核心机制:
- Java源程序(
.java
)编译为与平台无关的字节码文件(.class
),而非直接生成机器码。 - 字节码由**Java虚拟机(JVM)**解释执行,JVM将字节码转换为目标平台的机器指令。
- Java源程序(
- 关键特点:
- 一次编译,到处运行:只要目标平台安装对应的JVM,同一份
.class
文件即可运行。 - 性能权衡:解释执行比C/C++直接编译为机器码效率低,但跨平台性强。
- 一次编译,到处运行:只要目标平台安装对应的JVM,同一份
- 对比C/C++:
- C/C++需针对不同平台重新编译生成特定机器码,Java通过JVM屏蔽底层差异。
- C/C++需针对不同平台重新编译生成特定机器码,Java通过JVM屏蔽底层差异。
🔐 2. Java的安全性
- 语言层级安全:
- 取消指针:用引用替代指针,避免内存非法访问和越界问题。
- 垃圾回收(GC):自动管理内存,防止内存泄漏和野指针。
- 异常处理:
try/catch/finally
结构化捕获错误,增强健壮性。 - 强制类型检查:防止不安全的类型转换。
- 底层安全机制:
- 字节码校验器:验证字节码合法性。
- 类加载器(ClassLoader):隔离不同类访问权限。
- 运行时内存布局:防止内存冲突。
- 文件访问限制:沙箱机制限制恶意代码。
📦 3. Java三大版本
版本 | 全称 | 应用场景 | 特点 |
---|---|---|---|
J2SE | Java 2 Standard Edition | 桌面应用、基础开发 | 包含核心类库(I/O、网络等) |
J2EE | Java 2 Enterprise Edition | 企业级应用(电商、ERP系统) | 扩展Servlet/JSP/EJB等组件 |
J2ME | Java 2 Micro Edition | 嵌入式设备(功能机、机顶盒) | 精简J2SE,专有API(不用于Android) |
关系:J2EE包含J2SE,J2ME包含部分J2SE核心类。
🛠️ 4. JVM、JDK、JRE 核心概念
- JVM(Java虚拟机):
- 执行字节码的虚拟计算机,实现跨平台(不同OS有专属JVM)。
- 核心功能:解释字节码、内存管理、安全控制。
- JRE(Java运行环境):
- = JVM + 核心类库(如
rt.jar
)。 - 仅支持运行已编译的Java程序(无编译能力)。
- = JVM + 核心类库(如
- JDK(Java开发工具包):
- = JRE + 开发工具(
javac
编译器、jar
打包工具等)。 - 开发者必需,支持开发、调试、运行。
- = JRE + 开发工具(
关系总结:JDK ⊃ JRE ⊃ JVM 。
📝 5. Java三种注释类型
类型 | 语法 | 用途 |
---|---|---|
单行注释 | //注释内容 | 临时注释单行代码 |
多行注释 | /* 注释内容 */ | 注释多行代码(不可嵌套) |
文档注释 | /** 注释内容 */ | 生成API文档(通过javadoc 工具) |
示例:
/** * 动物类(文档注释) * @author Developer */ public class Animal { int age; // 单行注释:年龄属性 /* 多行注释: void eat() { ... } */ }
🧮 6. 8种基本数据类型及字节数
数据类型 | 关键字 | 字节数 | 取值范围 |
---|---|---|---|
字节型 | byte | 1 | -128 ~ 127 |
短整型 | short | 2 | -32768 ~ 32767 |
整型 | int | 4 | -2³¹ ~ 2³¹-1 |
长整型 | long | 8 | -2⁶³ ~ 2⁶³-1 |
单精度浮点型 | float | 4 | 科学计数法(约±3.4e³⁸) |
双精度浮点型 | double | 8 | 科学计数法(约±1.8e³⁰⁸) |
字符型 | char | 2 | Unicode字符(0~65535) |
布尔型 | boolean | 1位 | true /false |
布尔型大小:实际占用1位,但JVM通常以1字节处理。
🔄 7. i++
vs ++i
区别与示例
- 共同点:
- 等价于
i = i + 1
,若独立成句(如i++;
),效果相同。
- 等价于
- 不同点:
i++
(后置自增):先取值,后自增。int a = 5; int b = a++; // b=5, a=6
++i
(前置自增):先自增,后取值。int x = 5; int y = ++x; // y=6, x=6
关键:在表达式中影响其他变量的计算结果。
⚡ 8. &
vs &&
与 |
vs ||
&
和|
:&
:按位与(操作整数)或逻辑与(操作布尔值)。|
:按位或(整数)或逻辑或(布尔值)。- 特点:无论左侧结果如何,右侧操作数都会执行。
&&
和||
:- 短路特性:
&&
:左侧为false
时,右侧不执行。||
:左侧为true
时,右侧不执行。
- 高效场景:
if (list != null && list.size() > 0) // 避免空指针异常
- 短路特性:
优先使用:短路运算符(
&&
/||
)提升效率。
⏩ 9. 高效计算:2乘以8的最优解法
- 答案:
2 << 3
- 原理:
- 左移运算(
<< n
)等价于乘以2的n次方。 2 << 3
= 2 × 2³ = 16。
- 左移运算(
- 优势:
- CPU直接支持位运算,效率高于乘法指令。
扩展:
a * 8
→a << 3
(适用于任意整数)。
🔄 10. 基本数据类型转换规则
- 自动转换(隐式):
- 小范围 → 大范围(如
byte
→int
)。 - 方向:
byte → short → int → long → float → double
。
- 小范围 → 大范围(如
- 强制转换(显式):
- 大范围 → 小范围需手动转型,可能丢失精度或溢出。
double d = 10.24; long l = (long) d; // l=10(精度丢失)
- 特殊规则:
byte
/short
/char
参与运算时自动提升为int
。
📚 Java面试宝典:核心知识点详解(下)
🔄 11. if多分支 vs switch多分支
特性 | if-else if-else | switch-case |
---|---|---|
适用场景 | 分支较少(≤5),条件为区间或逻辑表达式 | 分支多且为等值判断(整型/枚举/字符串) |
执行逻辑 | 条件从上至下判断,匹配即停止 | 从匹配入口执行,不加break会穿透 |
条件类型 | 支持任意布尔表达式(> , != , 等) | 仅支持等值比较(不可用> , < ) |
性能 | 分支多时效率较低 | 跳转表实现,多分支时效率更高 |
示例:
// if处理区间判断 if (score >= 90) grade = "A"; else if (score >= 80) grade = "B"; // switch处理固定值 switch (level) { case 1: System.out.println("初级"); break; case 2: System.out.println("中级"); } // 若level=2,会输出"中级"并穿透后续case
🔄 12. while vs do-while循环
循环类型 | 执行顺序 | 首次条件=false时 | 适用场景 |
---|---|---|---|
while | 先判断 ⇒ 后执行 | 循环体一次都不执行 | 需要前置条件检查 |
do-while | 先执行 ⇒ 后判断 | 至少执行一次循环体 | 必须执行一次的场景 |
关键区别:
int i = 0; while (i > 0) { // 不执行 System.out.println("while循环"); } do { // 执行一次 System.out.println("do-while循环"); } while (i > 0);
⏩ 13. break 与 continue 作用
关键字 | 作用 | 示例场景 |
---|---|---|
break | 立即退出整个循环体 | 满足条件时提前终止循环 |
continue | 跳过本次循环,进入下一次迭代 | 跳过无效数据,继续处理后续元素 |
嵌套循环:
outer: for (int i=0; i<5; i++) { for (int j=0; j<5; j++) { if (j == 3) break outer; // 跳出外层循环 if (j == 1) continue; // 跳过j=1的本次迭代 } }
🧮 14. 递归算法示例:计算 n!
public static int factorial(int n) { if (n == 1) return 1; // 递归出口 return n * factorial(n - 1); // 递归调用
}
// 调用:factorial(5) = 120
⚖️ 15. 递归的优缺点
优点 | 缺点 |
---|---|
代码简洁,描述问题自然 | 效率低(函数调用开销大) |
解决复杂问题(如树遍历) | 栈溢出风险(深度过大) |
数学定义直观映射(如斐波那契) | 难调试和维护 |
使用原则:
- 必须有明确的递归出口
- 深度可控(一般 ≤ 1000 层)
- 避免重复计算(可用缓存优化)
📦 16. 数组核心特性
- 类型统一:所有元素类型相同(声明时指定)
- 长度固定:创建后不可改变(
arr.length
) - 内存连续:分配连续空间,索引访问(
O(1)
) - 默认值:
int
→0
,double
→0.0
boolean
→false
, 引用类型 →null
- 索引从0开始:有效范围
[0, length-1]
🔢 17~19. 三大排序算法
1. 冒泡排序(优化版)
void bubbleSort(int[] arr) { for (int i = 0; i < arr.length-1; i++) { boolean swapped = false; for (int j = 0; j < arr.length-1-i; j++) { if (arr[j] > arr[j+1]) { int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; swapped = true; } } if (!swapped) break; // 无交换时提前终止 }
}
2. 选择排序
void selectionSort(int[] arr) { for (int i = 0; i < arr.length-1; i++) { int minIndex = i; for (int j = i+1; j < arr.length; j++) { if (arr[j] < arr[minIndex]) minIndex = j; } int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; }
}
3. 插入排序
void insertionSort(int[] arr) { for (int i = 1; i < arr.length; i++) { int key = arr[i], j = i-1; while (j >= 0 && arr[j] > key) { arr[j+1] = arr[j]; // 后移元素 j--; } arr[j+1] = key; }
}
🔄 20. 可变参数(Varargs)特性
- 语法:
类型... 参数名
(如String... names
) - 规则:
- 必须是方法最后一个参数
- 内部按数组处理(
names.length
获取数量) - 调用灵活:
print("A"); // 等价于 print(new String[]{"A"}) print("A", "B", "C"); // 等价于 print(new String[]{"A","B","C"})
- 禁止:不能与同类型数组方法重载(编译冲突)
典型应用:
String.format()
、日志工具等方法
🧩 21. 类与对象关系
概念 | 定义 | 现实比喻 | 示例 |
---|---|---|---|
类 | 对象的模板(抽象) | 汽车设计图 | class Car { ... } |
对象 | 类的实例(具体) | 根据图纸造的实体车 | Car myCar = new Car() |
关键点:
- 类定义了属性(字段)和行为(方法)
- 对象通过
new
创建,每个对象拥有独立内存空间- 同一类的对象共享方法定义,但属性值不同
🆚 22. 面向过程 vs 面向对象
维度 | 面向过程 | 面向对象 |
---|---|---|
核心思想 | 以步骤为中心(函数驱动) | 以对象为中心(数据封装) |
代码组织 | 按功能拆分成函数 | 按现实实体抽象成类 |
典型语言 | C, Pascal | Java, C#, Python |
优势 | 简单问题高效 | 复杂系统易扩展、维护 |
核心特性 | 无封装、继承、多态 | 支持三大特性 |
方法重载和方法重写(覆盖)的区别
开发演进:
大型系统中,面向对象通过封装(隐藏细节)、继承(代码复用)、多态(接口统一)显著降低复杂度。
🔑 23. this 与 super 关键字
关键字 | 作用 | 使用场景 |
---|---|---|
this | 1. 指代当前对象 | 解决字段/局部变量同名冲突 |
2. 调用本类构造方法(this() ) | 构造方法重载时复用代码 | |
super | 1. 调用父类成员 | 访问被重写的父类方法 |
2. 调用父类构造方法(super() ) | 子类构造方法中初始化父类部分 |
约束:
this()
和super()
必须在构造方法首行- 不可在静态方法中使用(无"当前对象"概念)
⚙️ 24. static 关键字详解
四大用途:
- 静态变量:类级别共享(所有对象共用同一份)
class Student { static String school = "北大"; // 所有学生共享 }
- 静态方法:无需对象即可调用(禁止访问非静态成员)
Math.max(10, 20); // 经典用例
- 静态代码块:类加载时执行一次(初始化静态资源)
static { System.out.println("类已加载!"); }
- 静态内部类:不依赖外部类实例(可独立存在)
内存特性:
- 静态成员在方法区存储(非堆内存)
- 类加载时初始化,程序结束时销毁