Java基础面试题及答案
一、面向对象基础
1. 什么是面向对象?
面向对象是一种编程范式,它使用"对象"来设计应用程序和计算机程序。面向对象的程序由对象组成,每个对象包含对数据的操作方法。面向对象的核心特性包括封装、继承、多态和抽象。
2. 封装、继承、多态、抽象的含义?
- 封装 :将数据和方法组合在一个单元(类)中,隐藏内部实现细节,只暴露必要的接口。
- 继承 :子类继承父类的属性和方法,实现代码复用,并可以添加新的属性和方法。
- 多态 :同一个方法在不同对象上有不同的实现方式,包括编译时多态(方法重载)和运行时多态(方法重写)。
- 抽象 :忽略细节,专注于本质特征,通过抽象类和接口实现。
3. 什么是构造函数?有什么特点?
构造函数是一种特殊的方法,用于创建对象时初始化对象。特点:
- 名称与类名相同
- 没有返回类型
- 当创建对象时自动调用
- 可以重载
- 如果没有显式定义构造函数,编译器会提供一个默认无参构造函数
4. 方法重载与重写的区别?
- 重载(Overloading) :发生在同一个类中,方法名相同,参数列表不同(类型、数量或顺序),返回类型可以不同。
- 重写(Overriding) :发生在父类和子类之间,方法名、参数列表和返回类型都相同,子类重写父类的方法以提供不同的实现。
5. 抽象类与接口的区别?
- 抽象类 :可以包含抽象方法和非抽象方法,可以有构造函数,可以有成员变量,只能单继承。
- 接口 :只能包含抽象方法(Java 8后可以有默认方法和静态方法),不能有构造函数,成员变量都是静态常量,支持多实现。
6. final、finally、finalize的区别?
- final :修饰类表示不能被继承;修饰方法表示不能被重写;修饰变量表示常量,不能被修改。
- finally :异常处理的一部分,用于定义无论是否发生异常都会执行的代码块,通常用于释放资源。
- finalize :Object类的方法,在对象被垃圾回收前调用,用于释放资源,Java 9后已被标记为过时。
二、数据类型与字符串
7. Java的基本数据类型有哪些?对应的包装类是什么?
- 基本数据类型:byte、short、int、long、float、double、char、boolean
- 包装类:Byte、Short、Integer、Long、Float、Double、Character、Boolean
8. 自动装箱与拆箱的含义?
- 自动装箱 :基本数据类型自动转换为对应的包装类对象。
- 自动拆箱 :包装类对象自动转换为对应的基本数据类型。
9. String、StringBuilder、StringBuffer的区别?
- String :不可变类,每次修改都会创建新对象,适用于少量操作的字符串。
- StringBuilder :可变类,非线程安全,效率高,适用于单线程环境下的大量字符串操作。
- StringBuffer :可变类,线程安全,效率较低,适用于多线程环境下的字符串操作。
10. ==与equals的区别?
- == :对于基本数据类型,比较值是否相等;对于引用数据类型,比较引用是否指向同一个对象。
- equals :默认比较引用是否相等,可被重写为比较内容是否相等(如String类)。
11. 什么是常量池?
常量池是Java内存中的一块区域,用于存储字符串常量和基本数据类型的包装类常量。当创建字符串时,如果常量池中已存在相同内容的字符串,则直接返回引用,而不创建新对象。
三、集合框架
12. Java集合框架的主要接口有哪些?
- Collection :所有集合的根接口,包含List、Set、Queue等子接口。
- List :有序、可重复的集合,如ArrayList、LinkedList、Vector。
- Set :无序、不可重复的集合,如HashSet、TreeSet、LinkedHashSet。
- Map :键值对集合,如HashMap、TreeMap、LinkedHashMap、Hashtable。
13. ArrayList与LinkedList的区别?
- ArrayList :基于动态数组实现,查询效率高(O(1)),增删效率低(需要移动元素,O(n)),适用于频繁查询的场景。
- LinkedList :基于双向链表实现,查询效率低(O(n)),增删效率高(O(1)),适用于频繁增删的场景。
14. HashMap的工作原理?
HashMap基于哈希表实现,通过键的hashCode计算存储位置。主要特点:
- 允许null键和null值
- 非线程安全
- 存储结构:JDK 1.8前是数组+链表,JDK 1.8后是数组+链表/红黑树(链表长度超过8时转换为红黑树)
- 扩容机制:当元素数量超过阈值(容量*负载因子)时,扩容为原来的2倍
15. HashSet如何保证元素不重复?
HashSet底层使用HashMap实现,将元素作为HashMap的键,值为一个固定对象。通过HashMap的键不重复特性来保证元素不重复。
16. TreeMap与HashMap的区别?
- TreeMap :基于红黑树实现,按键排序,查询时间复杂度O(log n),适用于需要排序的场景。
- HashMap :基于哈希表实现,不保证顺序,查询时间复杂度O(1)(平均情况),适用于不需要排序的场景。
四、异常处理
17. Java异常体系的结构?
- Throwable :所有异常的父类,分为Error和Exception。
- Error :严重错误,如OutOfMemoryError,程序无法处理。
- Exception :可处理的异常,分为CheckedException和UncheckedException。
- CheckedException :编译时异常,如IOException,必须显式处理。
- UncheckedException :运行时异常,如NullPointerException,可选择性处理。
18. try-catch-finally的执行顺序?
- 首先执行try块中的代码。
- 如果发生异常,跳转到对应的catch块执行。
- 无论是否发生异常,finally块中的代码都会执行(除非在try或catch块中调用System.exit())。
19. throw与throws的区别?
- throw :用于方法内部,抛出一个具体的异常对象。
- throws :用于方法声明,指定方法可能抛出的异常类型。
20. 什么是异常链?
异常链是指在捕获一个异常后,抛出另一个异常,并将原始异常作为新异常的原因。通过这种方式,可以保留异常的原始信息。
五、多线程
21. 线程的创建方式有哪些?
- 继承Thread类 :重写run()方法。
- 实现Runnable接口 :实现run()方法,将实例传给Thread对象。
- 实现Callable接口 :实现call()方法,通过FutureTask获取返回值。
- 线程池 :使用ExecutorService创建线程。
22. 线程的状态有哪些?
- 新建(New)
- 就绪(Runnable)
- 运行(Running)
- 阻塞(Blocked)
- 等待(Waiting)
- 超时等待(Timed Waiting)
- 终止(Terminated)
23. synchronized与volatile的区别?
- synchronized :可以修饰方法和代码块,保证原子性、可见性和有序性,是重量级锁。
- volatile :只能修饰变量,保证可见性和有序性,不保证原子性,是轻量级同步机制。
24. 什么是线程安全?如何实现线程安全?
线程安全是指多线程环境下,程序的执行结果与单线程环境下一致。实现方式:
- 使用synchronized
- 使用volatile
- 使用Lock接口
- 使用线程安全的集合类(如ConcurrentHashMap)
- 使用原子类(如AtomicInteger)
25. 什么是死锁?如何避免死锁?
死锁是指两个或多个线程互相持有对方需要的资源,导致所有线程都无法继续执行。避免死锁的方法:
- 按顺序获取锁
- 设置锁超时
- 使用Lock接口的tryLock()方法
- 减少锁的持有时间
六、其他核心知识点
26. 什么是反射机制?有什么用途?
反射机制是指程序在运行时可以获取自身的信息,并操作类或对象的内部属性和方法。用途:
- 动态创建对象
- 动态调用方法
- 访问私有成员
- 实现框架(如Spring)
27. 什么是注解?有什么用途?
注解是一种标记性接口,用于为代码添加元数据。用途:
- 提供编译时检查(如@Override)
- 生成文档(如@param)
- 运行时处理(如Spring的@Autowired)
28. JVM的内存模型?
JVM内存模型分为:
- 程序计数器:线程私有,存储当前线程执行的字节码行号。
- 虚拟机栈:线程私有,存储方法的局部变量、操作数栈、返回地址等。
- 本地方法栈:线程私有,为Native方法服务。
- 堆:线程共享,存储对象实例和数组。
- 方法区:线程共享,存储类信息、常量、静态变量等。
29. 什么是垃圾回收?常见的垃圾回收算法有哪些?
垃圾回收是指自动回收不再使用的对象内存。常见算法:
- 标记-清除(Mark-Sweep)
- 复制(Copying)
- 标记-整理(Mark-Compact)
- 分代收集(Generational Collection)
30. 类加载器的作用?有哪些类型?
类加载器用于将class文件加载到JVM中。类型:
- 启动类加载器(Bootstrap ClassLoader)
- 扩展类加载器(Extension ClassLoader)
- 应用程序类加载器(Application ClassLoader)
- 自定义类加载器
31. 什么是单例模式?有哪些实现方式?
单例模式确保一个类只有一个实例,并提供全局访问点。实现方式:
- 饿汉式
- 懒汉式(线程不安全)
- 懒汉式(线程安全,双重检查锁定)
- 静态内部类
- 枚举
32. 什么是工厂模式?有哪些类型?
工厂模式用于创建对象,隐藏创建细节。类型:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
33. 什么是序列化与反序列化?
- 序列化 :将对象转换为字节流的过程。
- 反序列化 :将字节流转换为对象的过程。
实现方式:让类实现Serializable接口。
34. 什么是泛型?有什么用途?
泛型允许在定义类、接口和方法时使用类型参数,在使用时指定具体类型。用途:
- 提高代码复用性
- 提供编译时类型检查
- 避免类型转换