java面试八股这一篇就够之java基础篇
1. 封装的核心目的是什么?请举例说明
答案:封装通过访问控制(如private)隐藏内部细节,仅暴露接口。例如,User类的密码字段设为private,仅通过setPassword()方法修改,防止外部直接赋值。封装实现专业分工(代码复用)和数据保护(如银行账户安全)。
2. 继承中 “子类不能继承父类私有属性”,构造方法是否可被继承?
答案:构造方法不可被继承。子类通过super()调用父类构造方法,但父类私有构造方法仅允许在本类中使用,子类无法直接访问。
3. 多态的实现条件有哪些?向上转型和向下转型的区别?
答案:条件:① 继承 / 实现;② 方法重写;③ 父类引用指向子类对象(向上转型)。
- 向上转型(
Animal a = new Dog()):JVM 自动完成,安全,子类特有方法不可用。 - 向下转型(
Dog d = (Dog)a):需强制转换,不安全,可能抛ClassCastException。
4. JDK、JRE、JVM 的关系是什么?
答案:JDK ⊃ JRE ⊃ JVM。JDK 含开发工具(如javac),JRE 含运行环境(JVM + 类库),JVM 负责执行字节码。开发需 JDK,运行只需 JRE。
5. 基本数据类型和封装类的核心区别(至少 3 点)
答案:
- 存储:基本类型存栈(直接值),封装类存堆(栈存引用)。
- 默认值:基本类型有默认值(如
int=0),封装类默认null。 - 泛型:集合只能用封装类(如
List<Integer>)。 - 传递:基本类型按值传递,封装类按引用传递。
6. main 方法为何必须是public static void?
答案:
public:JVM 需全局访问入口。static:无需实例化类即可调用(启动时无对象)。void:无返回值(JVM 不接收返回结果)。
7. ==和equals在String中的区别?请举例
答案:
"==": 既可以比较基本数据类型(比较值是否相等),也可以比较引用数据类型(比较的是地址是是否相等)
equals():可以用于比较引用数据类型(一般调用的就是==,重新后就是比较的是内容值了),String,Data 类就是重写了。
java
String s1 = "abc", s2 = "abc", s3 = new String("abc");
System.out.println(s1 == s2); // true(常量池复用)
System.out.println(s1 == s3); // false(堆对象不同)
8. Object 类的hashCode和equals必须同时重写吗?为什么?
答案:必须。若equals为true但hashCode不同,存入HashMap时会被视为不同键,导致get失败。阿里规范要求:重写equals必重写hashCode。例如,自定义User类需保证u1.equals(u2) → u1.hashCode()==u2.hashCode()。
9. short s1 = 1; s1 += 1;为何不报错?而 s1 = s1 + 1;报错?
答案:
s1 += 1:隐式强转(等价(short)(s1+1)),JVM 自动处理。s1 = s1 + 1:int类型运算结果无法直接赋值给short,需显式转换。
10. &和&&的短路特性如何避免空指针?
答案:&&短路:左侧为false时,右侧不执行。例如:
obj != null && obj.getValue() > 0,若obj为null,左侧false直接终止,避免NullPointerException。
11. Integer 缓存机制的范围是?对new Integer(128)是否生效?
答案:缓存-128~127(通过IntegerCache实现)。new Integer(128)直接创建新对象,不命中缓存,因此new Integer(128) == new Integer(128)为false。
Integer a=100,b=100,c=129,d=129
sout(a==b) //true
sout(c==d) //false
12. final修饰变量、方法、类的区别?
答案:
- 变量:基本类型值不可变,引用类型不可指向新对象(对象内容可变)。
- 方法:不可重写(可重载),子类无法覆盖。
- 类:不可被继承(如
String类)。
13. finally块一定会执行吗?哪些情况不执行?
答案:不一定。不执行场景:
try块未执行(如提前return)。- 调用
System.exit(0)终止 JVM。 finally中含return,会覆盖try/catch的return。
14. 深拷贝和浅拷贝的本质区别?请举例
答案:
- 浅拷贝:复制对象本身,引用类型字段指向原对象(如
Student拷贝后,Teacher引用不变)。 - 深拷贝:复制对象及所有引用字段(如递归拷贝
Teacher)。
示例:修改浅拷贝的Teacher属性,原对象同步变化;深拷贝则独立。
15. String str = "a"和new String("a")创建了几个对象?
答案:
str = "a":常量池 1 个对象(复用已有 "a")。new String("a"):堆中 1 个对象,若常量池无 "a",先创建常量池对象,共 2 个。
16. 抽象类能否有构造方法?能否被final修饰?
答案:
- 可以有构造方法(供子类
super()调用)。 - 不能被
final修饰:抽象类需被继承,final类禁止继承,矛盾。
17. 静态方法为何不能调用非静态成员?
答案:静态方法属于类,非静态成员依赖对象实例。调用非静态成员需先创建对象,而静态方法无隐含this指针,无法访问。
18. 重载(Overload)和重写(Override)的核心区别?
答案:
| 维度 | 重载(同一类) | 重写(父子类) |
|---|---|---|
| 方法名 | 相同 | 相同 |
| 参数列表 | 不同(类型 / 个数) | 相同 |
| 返回类型 | 无限制 | 子类可更具体(协变返回) |
| 多态类型 | 编译时多态 | 运行时多态 |
| 访问权限 | 无限制 | 子类≥父类(如public≥protected) |
19. 简述 Java 的四种引用类型及应用场景
答案:
- 强引用(默认):对象存活,如
Object obj = new Object()。 - 软引用(
SoftReference):内存不足时回收,用于缓存。 - 弱引用(
WeakReference):GC 扫描即回收,如HashMap的key。 - 虚引用(
PhantomReference):跟踪 GC,配合引用队列。
20. 序列化中transient的作用?如何实现深拷贝?
答案:
transient:标记字段不参与序列化(如transient String password)。- 深拷贝:实现
Cloneable接口,递归复制引用类型字段(如Student拷贝时克隆Teacher对象)。
21. 泛型的类型擦除是什么?为什么需要它?
答案:编译后泛型信息被擦除,用原始类型(如List<String>→List)。目的是兼容旧代码,保证字节码与 JVM 版本无关。
22. 访问修饰符的作用域(表格形式)
答案:
| 修饰符 | 当前类 | 同包 | 子类(不同包) | 其他包 |
|---|---|---|---|---|
| public | √ | √ | √ | √ |
| protected | √ | √ | √ | × |
| default | √ | √ | × | × |
| private | √ | × | × | × |
23. float f = 3.4;为何错误?如何修正?
答案:3.4是double类型,需显式转换:float f = (float)3.4; 或加F后缀:float f = 3.4F;。
24. StringBuilder为何比StringBuffer快?
答案:StringBuffer方法加synchronized(线程安全),StringBuilder无同步(非线程安全),单线程场景性能更高。
25. main方法被private修饰能否运行?为什么?
答案:编译通过,但运行报错 “main not public”。JVM 要求main必须public,否则无法访问入口方法。
26. Object的wait()和sleep()的区别?
答案:
wait():释放对象锁,需在synchronized中调用,用于线程间通信。sleep():不释放锁,线程休眠,可在任意代码中调用。
27. 简述反射的作用及应用场景
答案:动态获取类信息(如字段、方法),运行时创建对象、调用方法。应用:框架(Spring 依赖注入)、单元测试、反序列化等。
28. 为什么char能存中文?
答案:Java 使用 Unicode 编码(16 位),中文在\u4E00-\u9FFF范围内,char(2 字节)可直接存储。
29. 数组和集合的区别(至少 3 点)
答案:
- 类类型:数组可存基本类型和对象,集合仅存对象。
- 长度:数组固定,集合动态扩展(如
ArrayList)。 - 方法:集合提供
addAll、iterator等丰富方法,数组无。
30. 简述 Java 异常体系(Error vs Exception)
答案:
-
Error:系统级错误(如OutOfMemoryError),程序无法处理,只能终止。 -
Exception:程序级异常,分两类:- 受检异常(Checked):编译时必须处理(如
IOException)。 - 运行时异常(Unchecked):无需强制处理(如
NullPointerException)。 - String、StringBuffer、Stringbuilder有什么区别?
- 受检异常(Checked):编译时必须处理(如
31.String、StringBuffer、Stringbuilder有什么区别?
一句话总结
在 Java 中,String、StringBuffer、StringBuilder都是用于处理字符串的类,String不可变,每次修改生成新对象;StringBuffer和StringBuilder可变。StringBuffer线程安全但性能较低,StringBuilder非线程安全但效率更高。单线程用StringBuilder,多线程用StringBuffer,少量操作用String。
详细解析
在 Java 中,String、StringBuffer 和 StringBuilder 是处理字符串的核心类,它们的核心区别在于可变性、线程安全性和性能。以下是详细对比及使用场景建议:
一、核心对比表
| 特性 | String | StringBuffer | StringBuilder |
|---|---|---|---|
| 可变性 | 不可变(Immutable) | 可变(Mutable) | 可变(Mutable) |
| 线程安全 | 线程安全(天然不可变) | 线程安全(方法用synchronized修饰) | 非线程安全 |
| 性能 | 低(频繁修改产生大量对象) | 中(同步开销) | 高(无同步开销) |
| 使用场景 | 常量字符串、少量拼接 | 多线程环境下的字符串操作 | 单线程环境下的字符串操作 |
| 内存效率 | 低(频繁操作时) | 较高 | 最高 |