🔒 25. final vs abstract 关键字
| 关键字 | 修饰对象 | 作用 | 规则 |
|---|---|---|---|
| final | 类 | 禁止被继承 | final class MyClass { ... } |
| 方法 | 禁止被子类重写 | public final void func() | |
| 变量 | 变为常量(基本类型值不可变,引用类型地址不可变) | final int MAX = 100; | |
| abstract | 类 | 必须被继承 | abstract class Animal { ... } |
| 方法 | 必须被子类重写 | abstract void eat(); |
关键区别:
final Dog dog = new Dog("欧欧"); dog.name = "美美"; // ✅ 允许修改对象属性 dog = new Dog("亚亚"); // ❌ 禁止修改引用地址
⚖️ 26. final vs finally vs finalize
| 关键字 | 类别 | 作用 | 示例 |
|---|---|---|---|
| final | 修饰符 | 定义不可变实体(类/方法/变量) | final class Immutable { ... } |
| finally | 异常处理块 | 确保资源释放(无论是否发生异常) | try { ... } finally { conn.close(); } |
| finalize | Object类方法 | GC回收对象前调用的清理方法(已废弃) | protected void finalize() { /* 清理 */ } |
注意:
- Java 9+ 废弃
finalize(),推荐使用Cleaner或try-with-resourcesfinally块始终执行(除非System.exit()或 JVM 崩溃)
📦 27. java.lang.Object 的六个核心方法
equals(Object obj):对象等价性比较(默认比较地址)hashCode():返回对象哈希码(需与equals逻辑一致)toString():返回对象字符串表示(默认返回类名@地址)getClass():获取对象的运行时类wait()/notify()/notifyAll():线程间通信(需在同步块中使用)clone():创建并返回对象副本(需实现Cloneable接口)
重写规范:
@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return Objects.equals(name, user.name); }
🔑 28. 访问权限修饰符对比
| 修饰符 | 类内部 | 同包 | 不同包子类 | 全局 |
|---|---|---|---|---|
| private | ✅ | ❌ | ❌ | ❌ |
| 默认 | ✅ | ✅ | ❌ | ❌ |
| protected | ✅ | ✅ | ✅ | ❌ |
| public | ✅ | ✅ | ✅ | ✅ |
类修饰规则:
- 外部类仅支持
public或默认- 内部类可使用所有修饰符
🏗️ 29. 继承中的构造方法执行顺序
- 子类构造隐式调用
super():class Parent { Parent() { System.out.println("Parent构造"); } } class Child extends Parent { Child() { // 隐含 super(); System.out.println("Child构造"); } } // 输出:Parent构造 → Child构造 - 显式调用父类构造:
Child(int age) { super(age); // 必须位于首行 System.out.println("Child带参构造"); } - 多级继承顺序:
Object → 爷爷类 → 父类 → 子类
🆚 30. == vs equals()
| 操作符/方法 | 比较内容 | 示例 |
|---|---|---|
| == | 基本类型:值 | 10 == 10 → true |
| 引用类型:内存地址 | new String("A") == "A" → false | |
| equals() | 默认同 == | |
| 重写后按业务逻辑 | "A".equals(new String("A")) → true |
重写原则:
- 自反性:
x.equals(x) = true- 对称性:
x.equals(y) = y.equals(x)- 传递性:
x=y, y=z → x=z
🌀 31. Java多态详解
三大条件:
- 继承关系(
extends或implements) - 子类重写父类方法
- 父类引用指向子类对象:
Animal dog = new Dog()
转型示例:
// 向上转型(自动)
Animal animal = new Dog();
animal.eat(); // 调用Dog重写的eat() // 向下转型(需显式)
if (animal instanceof Dog) { Dog dog = (Dog) animal; dog.bark();
}
优势:代码扩展性强(新增子类不影响父类逻辑)
🗑️ 32. 垃圾回收机制(GC)
核心特性:
- 自动管理:JRE 后台回收无用对象(
java.lang.Object未覆盖时) - 回收区域:仅堆内存(不包含栈、方法区)
- 不可预测性:无法精确控制 GC 执行时机
触发时机:
- Eden 区满触发 Minor GC
- 老年代满触发 Full GC
- 手动建议:
System.gc()(不保证立即执行)
对象复活:
protected void finalize() { this.reference = this; // ❌ 已废弃,禁止使用
}
📦 33. 基本类型与包装类
| 基本类型 | 包装类 | 自动装箱/拆箱 |
|---|---|---|
byte | Byte | Integer i = 10; → 装箱 |
int | Integer | int n = i; → 拆箱 |
double | Double | Double d = 3.14; |
转换场景:
- 集合存储:
List<Integer> list = Arrays.asList(1, 2, 3); - 类型转换:
int age = Integer.parseInt("25"); - 空值处理:
Integer score = null;(基本类型不支持null)
🆚 34. Integer vs int
| 维度 | int | Integer |
|---|---|---|
| 类型 | 基本类型 | 包装类 |
| 默认值 | 0 | null |
| 内存占用 | 栈存储(4字节) | 堆存储(对象头+引用) |
| 比较 | == 比值 | == 比地址,equals 比值 |
| 缓存优化 | 无 | -128~127 缓存(IntegerCache) |
陷阱:
Integer a = 100, b = 100; a == b; // true(缓存范围内) Integer c = 200, d = 200; c == d; // false(超出缓存)
📅 35. java.util.Date vs java.sql.Date
| 类 | 所属包 | 用途 | 精度 |
|---|---|---|---|
| java.util.Date | java.util | 通用日期时间 | 毫秒级 |
| java.sql.Date | java.sql | 数据库日期(不含时间) | 到日(时间置零) |
转换示例:
// util.Date → sql.Date
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime()); // sql.Date → util.Date(自动向上转型)
java.util.Date date = sqlDate;
📂 36. 递归遍历目录文件
void listFiles(File dir) { File[] files = dir.listFiles(); if (files == null) return; for (File file : files) { if (file.isFile()) { System.out.println("文件: " + file.getPath()); } else { System.out.println("目录: " + file.getPath()); listFiles(file); // 递归遍历子目录 } }
}
// 调用: listFiles(new File("D:/Project"));
优化:使用
Files.walk()(Java 8 NIO)替代递归
37. Java编译输出结果
题目:关于Java编译,下面哪一个正确?
A. Java程序经编译后产生machine code
B. Java程序经编译后会生产byte code
C. Java程序经编译后会产生DLL
D. 以上都不正确
答案:B
解析:
- Java是解释型语言,编译生成字节码(byte code)(.class文件)而非机器码。
- DLL是C/C++编译的动态链接库,与Java无关。
38. 构造方法(Constructor)规则
题目:下列说法正确的有?
A. class中的construtor不可省略
B. construtor与class同名,但方法不能与class同名
C. construtor在一个对象被new时执行
D. 一个class只能定义一个construtor
答案:C
解析:
- A:类可省略构造方法(系统默认提供无参构造)。
- B:方法名可与类名相同(不推荐,违反规范)。
- D:类可定义多个构造方法(重载)。
- C正确:
new创建对象时自动执行匹配的构造方法。
39. 接口修饰符
题目:Java中接口的修饰符可以为?
A. private
B. protected
C. final
D. abstract
答案:D
解析:
- 接口默认为
abstract(可显式声明,通常省略)。 - 禁止使用
private/protected(仅支持public或默认包访问)。 final会阻止接口被实现,违反接口设计目的。
40. 继承中的构造方法执行顺序
题目:以下代码输出什么?
class A { public A() { System.out.println("A"); }
}
class B extends A { public B() { System.out.println("B"); } public static void main(String[] args) { B b = new B(); }
}
答案:B(输出AB)
解析:
- 子类构造方法隐式调用父类无参构造。
- 执行顺序:父类构造 → 子类构造。
41. 关键字使用错误
题目:下列关于关键字的使用说法错误的是?
A. abstract不能与final并列修饰同一个类
B. abstract类中可以有private成员
C. abstract方法必须在abstract类中
D. static方法能处理非static属性
答案:D
解析:
- D错误:static方法属于类,无法直接访问非static成员(需通过对象实例)。
- A:final类禁止继承,abstract类需被继承,冲突。
- B/C:抽象类可包含private属性和抽象方法。
42. 内存回收机制
题目:下列哪些语句关于内存回收的说法正确?
A. 程序员必须创建一个线程来释放内存
B. 内存回收程序负责释放无用内存
C. 内存回收程序允许程序员直接释放内存
D. 内存回收程序可以在指定时间释放内存
答案:B
解析:
- B正确:GC自动回收无用对象内存。
- A/C/D:程序员无法控制GC执行(仅能建议
System.gc())。
43. 合法标识符
题目:选出合理的标识符?
A. _sysl_111
B. 2 mail
C. $change
D. class
答案:A、C
解析:
- 合法规则:
- 可包含字母、数字、
_、$ - 不能以数字开头(B错误)
- 不能是关键字(D错误,
class是关键字)
- 可包含字母、数字、
44. 正确说法
题目:下列说法正确的是?
A. java.lang.Cloneable是类
B. java.lang.Runnable是接口
C. Double对象在java.lang包中
D. Double a=1.0是正确的java语句
答案:B、C、D
解析:
- A:
Cloneable是接口(标记接口)。 - B:
Runnable是接口(线程相关)。 - C:
Double包装类在java.lang。 - D:自动装箱(
double→Double)。
45. 类声明规则
题目:类名为"MyClass.java"的类可被工程中所有类访问,正确声明为?
A. private class MyClass
B. class MyClass extends Object
C. public class MyClass
D. public class MyClass extends Object
答案:C、D
解析:
- 全局访问需
public修饰(A/B默认包访问)。 extends Object可省略(所有类默认继承Object)。
46. 面向对象特征及生活案例
题目:面向对象的特征有哪些?举例说明。
答案:
- 封装
- 隐藏实现细节,暴露接口。
- 例:汽车驾驶(无需了解发动机原理,通过方向盘/油门控制)。
- 继承
- 子类复用父类属性和方法。
- 例:电商系统——
User为父类,Customer/Admin子类继承基础属性。
- 多态
- 同一接口不同实现。
- 例:支付系统——
Payment接口,Alipay/WeChatPay实现不同支付逻辑。
47. 内存泄漏 vs 内存溢出
题目:说明内存泄漏和内存溢出的区别及解决方案。
答案:
| 类型 | 内存泄漏(Memory Leak) | 内存溢出(OOM) |
|---|---|---|
| 定义 | 对象不再使用但未被GC回收 | 内存不足无法分配新对象 |
| 原因 | 长生命周期对象持有短生命周期对象引用 | 内存泄漏积累或数据量过大 |
| 检测工具 | VisualVM、MAT、JProfiler | JVM参数-XX:+HeapDumpOnOutOfMemoryError生成堆转储 |
| 解决方案 | - 及时解引用(如List.clear())- 避免静态集合类滥用 - 使用弱引用( WeakReference) | - 增加JVM内存 - 优化数据结构 - 分批次处理数据 |
48. Java序列化
题目:什么是Java序列化?如何实现?应用场景?
答案:
- 序列化:将对象状态转换为字节流(便于存储/传输)。
- 实现方式:
public class User implements Serializable { private String name; // 无需重写方法(默认序列化) } // 序列化 try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) { oos.writeObject(user); } - 应用场景:
- 分布式系统传输对象(RPC框架如Dubbo)。
- 缓存对象到硬盘(Redis持久化)。
- HTTP Session存储(Tomcat会话保存)。
49. 绕过构造方法创建对象
题目:不通过构造函数也能创建对象吗?
答案:可以,方式包括:
- 反射:
Class.newInstance()或Constructor.newInstance()。 - 克隆:实现
Cloneable接口,调用clone()。 - 反序列化:
ObjectInputStream.readObject()。
注意:克隆和反序列化不会调用构造方法。
50. 匿名内部类的继承与实现
题目:匿名内部类可不可以继承或实现接口?
答案:
- 可继承类:
new Thread() { @Override public void run() { /* 重写Thread方法 */ } }.start(); - 可实现接口:
Runnable r = new Runnable() { @Override public void run() { /* 实现Runnable */ } };
限制:
- 匿名内部类不能显式继承和实现同时存在(隐式继承Object)。
- 无法定义构造方法(需通过实例初始化块
{}模拟)。