一、Java基础知识
1. Java语言特点
题目: 请说明Java语言的主要特点?
答案:
- 面向对象:Java是纯面向对象的语言,支持封装、继承、多态
- 平台无关性:一次编译,到处运行(Write Once, Run Anywhere)
- 简单性:语法简洁,去掉了C++中的指针、多重继承等复杂特性
- 安全性:提供了安全管理机制,防止恶意代码攻击
- 多线程:内置多线程支持
- 健壮性:强类型检查、异常处理、垃圾回收
- 分布式:支持网络编程,便于开发分布式应用
2. JDK、JRE、JVM的关系
题目: 请解释JDK、JRE、JVM三者的关系?
答案:
- JVM(Java虚拟机):Java程序运行的环境,负责将字节码转换为机器码
- JRE(Java运行环境):包含JVM + Java核心类库,是Java程序运行的最小环境
- JDK(Java开发工具包):包含JRE + 开发工具(javac、java、javadoc等),是Java开发环境
关系:JDK > JRE > JVM
3. 基本数据类型
题目: Java有哪些基本数据类型?各占几个字节?
答案:
整型:
- byte:1字节,范围 -128 到 127
- short:2字节,范围 -32768 到 32767
- int:4字节,范围 -2^31 到 2^31-1
- long:8字节,范围 -2^63 到 2^63-1浮点型:
- float:4字节,单精度
- double:8字节,双精度字符型:
- char:2字节,Unicode字符布尔型:
- boolean:1字节(JVM中实际可能占4字节)
4. 自动装箱和拆箱
题目: 什么是自动装箱和拆箱?
答案:
- 自动装箱:基本类型自动转换为对应的包装类对象
- 自动拆箱:包装类对象自动转换为对应的基本类型
// 自动装箱
Integer i = 100; // 等价于 Integer i = Integer.valueOf(100);// 自动拆箱
int j = i; // 等价于 int j = i.intValue();
注意事项:
- Integer缓存池:-128到127的Integer对象被缓存
- 可能出现NullPointerException
5. equals()和==的区别
题目: equals()和==有什么区别?
答案:
- ==:
- 对于基本类型:比较值是否相等
- 对于引用类型:比较引用地址是否相等
- equals():
- 默认实现与==相同
- 可以重写来比较对象内容
- String类已重写equals()方法比较字符串内容
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = "hello";
String s4 = "hello";System.out.println(s1 == s2); // false,不同对象
System.out.println(s1.equals(s2)); // true,内容相同
System.out.println(s3 == s4); // true,字符串池中同一对象
二、面向对象编程
6. 面向对象三大特性
题目: 请详细说明面向对象的三大特性?
答案:
1. 封装(Encapsulation)
- 将数据和方法包装在类中
- 通过访问修饰符控制访问权限
- 隐藏内部实现细节
public class Person {private String name; // 私有属性public String getName() { // 公共方法return name;}public void setName(String name) {this.name = name;}
}
2. 继承(Inheritance)
- 子类继承父类的属性和方法
- 实现代码复用
- 支持方法重写
class Animal {protected void eat() {System.out.println("Animal is eating");}
}class Dog extends Animal {@Overrideprotected void eat() {System.out.println("Dog is eating");}
}
3. 多态(Polymorphism)
- 同一接口不同实现
- 运行时确定具体调用哪个方法
- 包括重载和重写
Animal animal = new Dog();
animal.eat(); // 调用Dog的eat方法
7. 重载和重写的区别
题目: 方法重载和重写有什么区别?
答案:
特性 | 重载(Overload) | 重写(Override) |
---|---|---|
定义 | 同一类中方法名相同,参数不同 | 子类重新实现父类方法 |
参数 | 必须不同 | 必须相同 |
返回值 | 可以不同 | 必须相同(或协变) |
访问修饰符 | 可以不同 | 不能降低访问权限 |
异常 | 可以不同 | 不能抛出更宽泛的检查异常 |
发生时期 | 编译期确定 | 运行期确定 |
8. 抽象类和接口的区别
题目: 抽象类和接口有什么区别?什么时候使用?
答案:
特性 | 抽象类 | 接口 |
---|---|---|
关键字 | abstract | interface |
继承 | 单继承 | 多实现 |
构造器 | 可以有 | 不能有 |
成员变量 | 任意类型 | public static final |
方法 | 抽象和具体方法 | 抽象方法(JDK8+支持默认方法) |
访问修饰符 | 任意 | public |
使用场景:
- 抽象类:is-a关系,有共同的属性和部分相同的行为
- 接口:can-do关系,定义行为规范
三、集合框架
9. Collection和Collections的区别
题目: Collection和Collections有什么区别?
答案:
- Collection:集合框架的根接口,定义了集合的基本操作
- Collections:工具类,提供了对集合操作的静态方法
// Collection是接口
Collection<String> list = new ArrayList<>();// Collections是工具类
Collections.sort(list);
Collections.reverse(list);
10. ArrayList和LinkedList的区别
题目: ArrayList和LinkedList有什么区别?
答案:
特性 | ArrayList | LinkedList |
---|---|---|
底层结构 | 动态数组 | 双向链表 |
随机访问 | O(1) | O(n) |
插入删除(头部) | O(n) | O(1) |
插入删除(尾部) | O(1) | O(1) |
插入删除(中间) | O(n) | O(n) |
内存占用 | 较小 | 较大(存储指针) |
线程安全 | 不安全 | 不安全 |
11. HashMap的实现原理
题目: 请详细说明HashMap的实现原理?
答案:
底层结构:
- JDK1.7:数组 + 链表
- JDK1.8+:数组 + 链表 + 红黑树
核心机制:
// 1. 计算hash值
int hash = key.hashCode();
hash = hash ^ (hash >>> 16); // 扰动函数// 2. 确定数组下标
int index = (n - 1) & hash; // n为数组长度// 3. 处理冲突
// - 链表长度 < 8:使用链表
// - 链表长度 >= 8:转换为红黑树
// - 红黑树节点 <= 6:转换为链表
扩容机制:
- 默认容量:16
- 负载因子:0.75
- 扩容阈值:容量 × 负载因子
- 扩容时容量翻倍
12. ConcurrentHashMap实现原理
题目: ConcurrentHashMap是如何实现线程安全的?
答案:
JDK1.7实现:
- 分段锁(Segment)机制
- 每个Segment继承ReentrantLock
- 降低锁的粒度
JDK1.8实现:
- 取消分段锁
- 使用CAS + synchronized
- 锁住链表或红黑树的首节点
- 进一步降低锁粒度
// JDK1.8 put方法核心逻辑
final V putVal(K key, V value, boolean onlyIfAbsent) {// 1. CAS尝试设置空位置if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null)))break;// 2. synchronized锁住首节点synchronized (f) {// 3. 插入链表或红黑树}
}
四、多线程
13. 进程和线程的区别
题目: 进程和线程有什么区别?
答案:
特性 | 进程 | 线程 |
---|---|---|
定义 | 程序的执行实例 | 进程中的执行单元 |
资源 | 拥有独立的内存空间 | 共享进程的内存空间 |
通信 | IPC(进程间通信) | 共享内存 |
创建开销 | 大 | 小 |
切换开销 | 大 | 小 |
影响范围 | 进程崩溃不影响其他进程 | 线程崩溃可能影响整个进程 |
14. 线程的状态
题目: Java线程有哪些状态?如何转换?
答案:
线程状态(Thread.State):
public enum State {NEW, // 新建RUNNABLE, // 运行(就绪+运行)BLOCKED, // 阻塞WAITING, // 等待TIMED_WAITING, // 超时等待TERMINATED // 终止
}
状态转换:
NEW → RUNNABLE:调用start()
RUNNABLE → BLOCKED:等待synchronized锁
BLOCKED → RUNNABLE:获得锁
RUNNABLE → WAITING:调用wait()、join()
WAITING → RUNNABLE:notify()、notifyAll()
RUNNABLE → TIMED_WAITING:sleep()、wait(timeout)
TIMED_WAITING → RUNNABLE:时间到或被唤醒
RUNNABLE → TERMINATED:run()方法结束
15. synchronized关键字
题目: 请详细说明synchronized的原理和使用?
答案:
使用方式:
// 1. 修饰实例方法
public synchronized void method() {}// 2. 修饰静态方法
public static synchronized void method() {}// 3. 修饰代码块
synchronized(object) {// 同步代码
}
实现原理:
- Java对象头:包含MarkWord,存储锁信息
- Monitor机制:基于操作系统的互斥量
- 字节码指令:monitorenter和monitorexit
锁升级过程(JDK1.6+):
无锁 → 偏向锁 → 轻量级锁 → 重量级锁
16. volatile关键字
题目: volatile关键字的作用是什么?
答案:
作用:
- 保证可见性:修改后立即写入主内存,其他线程读取时从主内存读取
- 禁止指令重排序:使用内存屏障
使用场景:
// 1. 状态标记
private volatile boolean flag = true;// 2. 双重检查锁单例模式
public class Singleton {private volatile static Singleton instance;public static Singleton getInstance() {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}
}
注意:volatile不保证原子性
17. 线程池
题目: 请说明线程池的工作原理和参数?
答案:
核心参数:
public ThreadPoolExecutor(int corePoolSize, // 核心线程数int maximumPoolSize, // 最大线程数long keepAliveTime, // 线程存活时间TimeUnit unit, // 时间单位BlockingQueue<Runnable> workQueue, // 工作队列ThreadFactory threadFactory, // 线程工厂RejectedExecutionHandler handler // 拒绝策略
)
工作流程:
- 提交任务到线程池
- 如果运行线程数 < corePoolSize,创建新线程
- 如果运行线程数 >= corePoolSize,任务加入队列
- 如果队列满了且运行线程数 < maximumPoolSize,创建新线程
- 如果运行线程数 >= maximumPoolSize,执行拒绝策略
常用线程池:
// 固定大小线程池
ExecutorService executor = Executors.newFixedThreadPool(10);// 缓存线程池
ExecutorService executor = Executors.newCachedThreadPool();// 单线程线程池
ExecutorService executor = Executors.newSingleThreadExecutor();// 定时任务线程池
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
五、JVM虚拟机
18. JVM内存结构
题目: 请详细说明JVM的内存结构?
答案:
运行时数据区域:
1. 程序计数器(PC Register)
- 线程私有
- 存储当前线程执行字节码的行号
- 唯一不会OutOfMemoryError的区域
2. Java虚拟机栈(JVM Stack)
- 线程私有
- 存储局部变量表、操作数栈、动态链接、方法出口
- StackOverflowError、OutOfMemoryError
3. 本地方法栈(Native Method Stack)
- 线程私有<