八股文-——java基础篇(2)
📦 模块一:面向对象深入(⭐⭐⭐⭐⭐ 必考)
怎么理解面向对象?封装、继承、多态简单说说
面向对象:把现实世界中的事务抽象为对象
封装、继承、多态
封装:指将对象的属性(数据)和行为(方法)结合在一起,对外隐藏对象的内部细节,仅通过对象提供的接口与外界交互。
继承和多态:
继承 :子类自动共享父类数据结构和方法的机制
多态:多态是指允许不同类的对象对同一消息作出响应。

多态体现在哪几个方面?解决了什么问题?
重载 重写 和 接口与实现
重载 : 同名方法中不同的参数,根据传入参数的不同 不一样的实现
重写 : 子类 对父类的方法进行 改造实现
接口与实现:
多态也体现在接口的使用上,多个类可以实现同一个接口,并且用接口类型的引用来调用这些类的方法。这使得程序在面对不同具体实现时保持一贯的调用方式。 ◦ 示例:多个类(如 Dog, Cat)都实现了一个 Animal 接口,当用 Animal 类型的引用来调用 makeSound 方法时,会触发对应的实现。
向上转型 和向下转型
可以使用父类类型的引用指向子类对象,这是向上转型。通过这种方式,可以在运行时期采用不同的子类实现。
Map<String,String> a= new HashMap<String,String>();
◦ 向下转型是将父类引用转回其子类类型,但在执行前需要确认引用实际指向的对象类型以避免 ClassCastException
要确认这个 a 的对象到底是不是子类类型
值传递和引用传递的区别?Java到底是哪种
Java只有值传递,传递的是引用的副本
面向对象的设计原则你知道有哪些吗
| 原则 | 一句话理解 | 技术类比 |
|---|---|---|
| SRP 单一职责 | 一个类只做一件事 | Unix 工具链:grep 只搜索,sort 只排序,wc 只计数 |
| OCP 开放封闭 | 加新功能不改旧代码 | VS Code 插件:加新功能装扩展,不用改编辑器内核 |
| LSP 里氏替换 | 子类能无缝替代父类 | USB 规范:任何品牌的 U 盘插进 USB 口都能用 |
| ISP 接口隔离 | 接口要小而专 | 微服务 API:用户服务只暴露用户接口,不暴露支付接口 |
| DIP 依赖倒置 | 依赖抽象不依赖具体 | 操作系统驱动层:OS 通过驱动接口控制硬件,不直接操作硬件 |
| LoD 最少知识 | 只和直接朋友打交道 | 网络 OSI 模型:应用层只跟传输层交互,不直接碰物理层 |
模块二:数据类型与运算细节(⭐⭐⭐⭐ 高频)
为什么金融计算用BigDecimal不用double?
double 是二进制近似值,天生不精确;遇到0.1 这样的数只能用不断的近似
BigDecimal 是十进制精确值,
BigDecimal 内部只存两样东西:
-
unscaled value(无标度值):一个超大整数
-
scale(标度 / 小数点位数):小数点在第几位
存放12.34
1,先存1234 的一个整数 unscaledValue
2.小数 1 scale
模块三:核心关键字与修饰符(⭐⭐⭐⭐⭐ 必考)
final / static
static :修饰类的成员(变量、方法、代码块)和内部类 ,将成员与类本身关联,而非与类的实例(对象)关联
| 关键字 | 含义 | 归属 | 数量 | 能否修改 |
|---|---|---|---|---|
| static | 静态 | 类 | 只有 1 份 | 可改 |
| final | 最终 | 变量 / 方法 / 类 | — | 不可改 / 不可重写 / 不可继承 |
| static final | 全局常量 | 类 | 只有 1 份 | 不可改 |
static 能不能访问非 static?
不能,因为 static 先存在,非 static 属于对象
final 变量必须初始化吗?
必须,声明时或构造器里
static 方法能不能重写?
不能,静态方法属于类,没有多态
String 为什么是 final?
安全、不可变、缓存哈希值
模块四:异常处理机制(⭐⭐⭐⭐⭐ 必考)
throw 和 throws 的区别?为什么有时不用throws?
throw:方法里,真扔出一个异常对象
throws:方法头,声明我可能会扔异常
// throws:声明我可能抛 IOException
public void readFile() throws IOException {
// throw:真的抛出异常对象
throw new IOException("文件找不到");
}
Java异常体系分类(Error/Exception、Checked/Unchecked)

Throwable 是所有异常类的父类
Error (错误): 表示运行环境的错误,
Exception (异常): 表示程序本身可以处理的异常情况。
非运行时异常(受检异常,Checked Exception): 这类异常在编译时就必须被捕获或者声明抛出。
运行时异常(非受检异常,Unchecked Exception 或 RuntimeException): 这类异常特指 RuntimeException 及其子类。
-
try{return "a"} finally{return "b"}返回什么?为什么?(经典坑题:返回
"b",finally覆盖try返回值)
📜 模块五:Object类与泛型基础(⭐⭐⭐⭐⭐ 必考)
-
Object类有哪些常用方法?
⭐⭐⭐⭐⭐
| 方法 | 作用 |
|---|---|
| getClass() | 获取运行时类对象 |
| hashCode() | 获取哈希码值 |
| equals() | 判断对象是否相等 |
| toString() | 转为字符串形式 |
| clone() | 实现对象浅克隆 |
| wait() | 线程等待释放锁 |
| notify() | 唤醒单个等待线程 |
| notifyAll() | 唤醒全部等待线程 |
| finalize() | GC 回收前执行(废弃) |
== 与 equals 有什么区别?
== 比较地址 equlas 比较内容
== 在 Java 里其实是个非常简单粗暴的比较方式。如果你比较的是基本数据类型(比如 int、double),那它就直接比数值是不是相等,这个没啥问题。 但如果你比较的是对象(引用类型),那 == 比较的就不是对象里面装的内容了,而是比较这两个变量是不是指向内存中同一个对象,也就是地址是否相同。
String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // 输出 false
== 在 Java 里其实是个非常简单粗暴的比较方式。如果你比较的是基本数据类型(比如 int、double),那它就直接比数值是不是相等,这个没啥问题。 但如果你比较的是对象(引用类型),那 == 比较的就不是对象里面装的内容了,而是比较这两个变量是不是指向内存中同一个对象,也就是地址是否相同。
String a = new String("hello");
String b = new String("hello");
System.out.println(a.equals(b)); // 输出 true
这里有个经典的面试陷阱,就是字符串常量池的问题。
String c = "hello"; String d = "hello"; System.out.println(c == d); // 输出 true
这里为什么 == 比较也是 true 呢?因为当你直接用双引号创建字符串的时候,JVM 会把它扔到一个叫"字符串常量池"的地方。如果池子里已经有了 "hello",那 d 就直接复用 c 指向的那个对象,所以它俩地址是一样的,== 自然就返回 true 了。
2.hashCode() 和 equals() 的关系?重写规范是什么?
如果两个对象equals 相等,它们的hashCode 必须相等
如果两个对象hashCode 相等,equals不一定相等(哈希碰撞)
如果 equals 不相等,hashCode可同可不同
规范:
重写equals()必须同时重写hashCode()
参与equals比较的属性,全部参与 hashCode 计算
保证属性相同的对象,哈希值一致
尽量让不同属性对象生成不同哈希值,减少碰撞
不遵守后果
存入HashSet、HashMap等哈希集合,会出现去重失败、查询不到数据。
3.什么是泛型?类型擦除是什么?
4.String、StringBuffer、StringBuilder的区别和联系
| 特性 | String | StringBuilder | StringBuffer |
|---|---|---|---|
| 不可变性 | 不可变 | 可变 | 可变 |
| 线程安全 | 是(不可变保证) | 否 | 是(同步) |
| 性能 | 低 | 高 | 中 |
| 适用场景 | 静态字符串 | 单线程频繁修改 | 多线程频繁修改 |
// String的不可变性
String str = "abc";
str
= str + "def"; // 新建对象,str指向新对象
// StringBuilder(单线程高效)
StringBuilder sb = new StringBuilder();
sb
.append("abc").append("def"); // 直接修改内部数组
// StringBuffer(多线程安全)
StringBuffer sbf = new StringBuffer();
sbf
.append("abc").append("def"); // 同步方法保证线程安全
🔍 模块六:反射、注解与对象创建(⭐⭐⭐ 进阶基础)
反射:
出现反射的历史原因:
解决的核心问题
实现框架底层逻辑
Spring、Mybatis、注解、动态代理等主流框架,全靠反射实现自动化。
统一通用操作
写一套代码,适配所有实体类,实现通用赋值、对象拷贝。
什么是反射

正常写法:编译期写死new 类名(),固定调用方法。
Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类中的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语言的反射机制。
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException, ClassNotFoundException, InstantiationException {
// 使用反射机制,根据这个字符串获得Class对象
Class<?> c = Class.forName(getName("className"));
System.out.println(c.getSimpleName());
// 获取方法
Method method = c.getDeclaredMethod(getName("methodName"));
// 绕过安全检查
method
.setAccessible(true);
// 创建实例对象(Class.newInstance() 已过时,使用 Constructor.newInstance())
TestInvoke testInvoke = (TestInvoke) c.getDeclaredConstructor().newInstance();
// 调用方法
method
.invoke(testInvoke);
}
应用场景 Spring IOC、MyBatis映射、JSON序列化
注解:
原理: 注解本质是一个 继承了 Annotation的特殊接口
元注解(修饰注解的注解)
-
@Target:注解能用在类 / 方法 / 属性哪里
-
@Retention
:
核心
,控制注解存活阶段
-
SOURCE:只源码存在,编译丢弃
-
CLASS:编译存在,运行丢弃(默认)
-
RUNTIME:运行时保留,反射能读取
-
-
@Documented:生成文档
-
@Inherited:子类继承父类注解
class="copy-panel" id="text-panel-iframe" src="chrome-extension://ipodhnfligecindaieefnaafgajiceoj/panel.html" style="position: fixed; width: 200px; height: 300px; z-index: 999999; background: white; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 1px; right: 10px; top: 50%; border-width: medium; border-style: none; border-color: currentcolor; border-image: initial; margin: 0px; padding: 0px; overflow: hidden; transform: translateY(-50%);">
更多推荐
所有评论(0)