Java 基础常见知识点与面试题总结(中):面向对象、Object 与 String

把 OOP、Object 和 String 这三块最容易连环追问的面试点拆开讲清,再重新串成一张完整知识图。

导读:中篇的难点不是知识点多,而是这些知识点互相会串。面向对象、equals/hashCode、String 常量池看起来分散,面试里往往会被连着追问。

系列阅读:上篇:语法、数据类型与方法下篇:异常、泛型、反射与 I/O

一、面向对象和面向过程,到底差在哪

很多人背这道题的时候容易空。更实用的答法是:面向过程更关注步骤,面向对象更关注对象和对象之间的职责分工。前者适合把任务拆成流程,后者适合构建可维护、可扩展的系统。

所以,面向对象的优势通常落在这三点:

  • 代码结构更稳定,维护成本更低。
  • 抽象得更好,复用性更强。
  • 随着需求变复杂,更容易做扩展而不是推翻重写。

面试里别把它讲成“面向对象一定比面向过程高级”。它们只是组织复杂度的方式不同,简单任务用过程式写法反而更直接。

二、对象、引用和构造方法,别在最开始就混了

new 出来的是对象实例,对象引用则是保存地址值的变量。引用可以为空,也可以多个引用同时指向同一个对象,这就是后面很多“修改一个对象为什么另一个也变了”的根源。

构造方法相关的高频点也就三个:

  1. 构造方法名必须和类名一致。
  2. 构造方法没有返回值,也不能写 void。
  3. 如果你没有手写构造方法,编译器会提供默认无参构造;一旦你自己声明了构造方法,这个默认无参构造就不会再自动存在。

所以,项目里一旦手动写了有参构造,又希望框架或序列化组件能无参实例化对象,通常还要补回无参构造。

三、封装、继承、多态,面试别只背定义

这三大特征每个人都能背,但拉开差距的是能不能把它们落到代码行为上。

  • 封装:隐藏内部状态,对外只暴露必要操作。真正价值是降低误用风险,而不是单纯把字段设成 private。
  • 继承:建立“是什么”的关系,复用共性逻辑,但不能为了少写代码乱继承。
  • 多态:父类引用指向子类对象,方法调用在运行时决定真正执行哪个实现。

面试最常见的一句补充是:多态能提高扩展性,但父类引用只能直接调用父类中声明过的方法。也就是说,子类特有的方法不能靠父类引用直接访问。

四、接口和抽象类,不是二选一的背题

很多人把这道题讲成列表对比,其实更容易记的方法是先看设计意图:接口更像能力约束,抽象类更像共享模板

维度 接口 抽象类
设计定位 定义行为规范 沉淀共性代码和状态
继承实现 一个类可实现多个接口 一个类只能继承一个抽象类
成员变量 默认 public static final 可定义普通成员变量
方法能力 可有 default、static、private 方法 可有抽象方法和普通方法

如果你在业务里需要一套统一能力规范,比如“可缓存、可导出、可序列化”,接口通常更合适;如果你已经有一批子类需要共享字段和默认实现,抽象类更顺手。

五、深拷贝、浅拷贝、引用拷贝,核心只看一件事

真正要分清的不是术语,而是内部引用对象有没有被复制

  • 引用拷贝:只是多一个引用,底层还是同一个对象。
  • 浅拷贝:外层对象复制了,但内部引用字段仍然共享。
  • 深拷贝:外层对象和内部引用对象都复制了一份。

所以,一旦对象里还有 Address、Profile、OrderItem 这种引用属性,只做 Object.clone 的默认实现通常是不够的。

浅拷贝和深拷贝的判断方式
Person p1 = ...;
Person p2 = p1.clone();

// 如果下面是 true,说明内部引用对象仍然共享,属于浅拷贝
System.out.println(p1.getAddress() == p2.getAddress());

六、Object 类最该掌握的,不是把 11 个方法全背出来

Object 当然是所有类的父类,但面试真正高频的是这几组关系:

  • equals 和 == 的区别。
  • hashCode 的作用,以及为什么要和 equals 一起重写。
  • toString 的价值。
  • wait、notify、notifyAll 的使用语义。

== 对基本类型比较值,对引用类型比较地址。equals 默认也是比较地址,只不过很多类会重写它,让它改为比较“内容”。String 就是最典型的例子。

而 hashCode 的意义,不在于“给对象一个编号”,而在于让哈希容器先快速定位桶位,再在桶内用 equals 做精确比较。也正因为这样,才会有那条经典规则:如果两个对象 equals 相等,那么它们的 hashCode 也必须相等

面试易错点:“hashCode 相等的两个对象一定相等”这句话是错的。hashCode 相等只能说明可能发生了哈希碰撞,还要继续看 equals。

七、String、StringBuilder、StringBuffer 该怎么选

这道题本质只看两个维度:可变性和线程安全。

类型 是否可变 线程安全 适用场景
String 不可变 天然安全 少量字符串处理
StringBuilder 可变 单线程高频拼接
StringBuffer 可变 多线程下共享缓冲区

String 的不可变性也经常被追问。更准确的答法是:不是因为它底层数组被 final 修饰就完了,而是因为底层存储不对外暴露、类本身不可继承、修改操作会返回新对象,这几层约束一起保证了不可变语义。

八、字符串常量池、intern 和 new String("abc") 是 String 面试的核心

字符串常量池的目标只有一个:复用相同内容的字符串,减少重复创建。因此,字面量形式创建的字符串,会优先进入常量池;new String 则一定会在堆上再创建一个新对象。

常量池与堆对象的区别
String a = "abc";
String b = "abc";
String c = new String("abc");

System.out.println(a == b); // true
System.out.println(a == c); // false
System.out.println(a.equals(c)); // true

再往前一步,intern 的作用可以理解成:帮你拿到常量池中那份“标准引用”。如果池里已经有同内容字符串,就直接返回那份引用;没有的话,就把当前字符串内容放进池里。

另外,字符串拼接题也很经典。简单说就是:

  • 编译期能确定结果的常量拼接,会发生常量折叠,直接进入常量池。
  • 运行期变量拼接,一般会转成 StringBuilder 的 append 逻辑。
  • 循环内大量用 + 拼接字符串,不如手写 StringBuilder 稳定。

九、中篇最值得记住的答题主线

如果你只想留住一条主线,那就是:对象如何被创建、如何被引用、如何判断相等、如何被字符串化和哈希化。这条线一旦建立起来,OOP、Object、String 就不会再显得零碎。

  1. 先讲对象和引用、构造方法。
  2. 再讲封装继承多态和接口/抽象类。
  3. 接着讲 equals/hashCode 和拷贝语义。
  4. 最后把 String 不可变、常量池、intern、拼接优化收尾。

一句话总结:中篇的重点不是背 API,而是理解“对象语义”。只要对象语义清楚,Java 中一大批高频题都会显得非常自然。

继续阅读:Java 基础常见知识点与面试题总结(下):异常、泛型、反射与 I/O

后浪云移动端信息流广告 后浪云主机服务 适合长期部署、独立站和海外机房需求。