JavaSE核心技术

Java基础与OOP模块

1. 面向对象的三大特性是什么?封装、继承、多态分别解决了什么问题?

面向对象三大特性是封装、继承、多态。
  • 封装:把类的属性和方法打包在一起,对外隐藏内部实现细节,只暴露公开访问方法。

    优点:保护内部数据,防止外部随意篡改;代码内聚,便于修改维护。

    缺点:过度封装会增加类的复杂度。

  • 继承:子类复用父类的代码和属性,建立类和类之间的父子关系。

    优点:代码复用,减少重复代码;便于建立类层次体系。

    缺点:强耦合,父类改动会影响所有子类。

  • 多态:同一个行为,不同对象有不同实现,调用时根据对象实际类型执行对应方法。

    优点:降低耦合,程序扩展性强,新增实现不用修改原有调用代码。

    缺点:运行时动态绑定,有微小性能损耗;代码阅读难度提升。

应用场景

  • 封装:实体类、业务类,把成员变量私有化,提供 get/set。
  • 继承:存在明确父子关系,多个子类共用父类通用逻辑,比如动物类作为父类,猫、狗作为子类。
  • 多态:面向接口编程,集合框架、Spring 依赖注入,同一个接口不同实现类切换。

2. 接口和抽象类的区别是什么?Java 8 之后接口发生了哪些变化(默认方法/静态方法)?

抽象类:用 abstract 修饰的类,不能实例化,可以包含普通成员变量、构造方法、抽象方法和普通方法(单继承)。
接口:是行为规范定义,Java8 之前只能定义常量和抽象方法;Java8 新增默认方法、静态方法;Java9 增加私有方法(多实现)。

优点

  • 抽象类:可以有构造函数,方便子类初始化;能有实例变量,可复用公共状态;支持普通方法。
  • 接口:一个类可以实现多个接口,解决 Java 单继承限制;只定义行为,和状态解耦,适合定义规范。 Java8 接口新增默认方法:接口可以提供方法默认实现,升级接口时,旧实现类不用强制重写,兼容老代码;静态方法属于接口本身,只能通过接口名调用。

缺点

  • 抽象类:Java 只支持单继承,一个类只能继承一个抽象类,限制扩展;父类改动会影响子类。
  • 接口:Java8 之前接口新增抽象方法,所有实现类必须全部重写,破坏向后兼容;默认方法存在多实现冲突问题,多个接口有同名默认方法时子类必须手动解决冲突。
核心区别简要总结:

① 抽象类是类,单继承;接口是规范,多实现

② 抽象类可以有构造器、实例变量;Java8 前接口只能常量 + 抽象方法

③ 抽象类用 extends;接口用 implements

④ 抽象类侧重代码复用;接口侧重行为定义

Java8 接口变化:增加默认方法 default和静态方法 static。

3. 方法重写(Override)和方法重载(Overload)的区别?

  • 重载 Overload:同一个类里面,方法名相同,参数列表不同(参数个数、类型、顺序),和返回值、访问修饰符无关。属于编译期静态绑定,编译阶段就确定调用哪个方法。
  • 重写 Override:子类定义和父类一模一样的方法(方法名、参数列表、返回值,协变返回类型允许),子类覆盖父类实现。属于运行期动态绑定,运行时看对象实际类型执行方法。(实现多态)

优点

  • 重载:同一个功能方法,支持多种参数形式,方法名统一,可读性好。
  • 重写:实现多态,子类可以改写父类逻辑,扩展原有行为。

缺点

  • 重载:只看参数,容易写出参数相近的方法,造成调用歧义。
  • 重写:父类方法签名改动,子类重写会失效;容易写错签名变成重载而非重写,建议加 @Override 注解检查。

应用场景

  • 重载:构造方法重载;工具类方法,比如多个版本 print 方法。
  • 重写:子类扩展父类逻辑,比如 Spring 中重写生命周期方法;equals、toString 方法重写。

4. String、StringBuffer、StringBuilder 的区别?为什么 String 设计为不可变?

  1. String:字符串,底层 Java8 是 char [],Java9 + 是 byte [],不可变,一旦创建内容不能修改,拼接会生成新 String 对象。
  2. StringBuffer:可变字符序列,方法加synchronized,线程安全。
  3. StringBuilder:可变字符序列,无同步锁,线程不安全。

为什么 String 设计成不可变: ① 字符串常量池复用,节约内存;② 哈希值只需要计算一次,适合做 HashMap 的 key;③ 线程天然安全,并发场景不用同步;④ 参数传递安全,防止被意外篡改。

优缺点:

  • String:优点常量池复用、hash 缓存、线程安全;缺点频繁拼接产生大量中间对象,GC 压力大。
  • StringBuilder:优点性能高;缺点多线程并发操作会数据错乱。
  • StringBuffer:优点多线程安全;缺点同步锁带来性能损耗。

应用场景:

  • String:字符串几乎不修改,定义固定文本。
  • StringBuilder:单线程循环拼接字符串(日常开发首选)。
  • StringBuffer:老项目多线程并发拼接,现在很少使用。

5.请说出 == 和 equals 方法的区别是什么?Object.equals 的默认行为是什么?

==:

  • 基本数据类型:== 比较值;基本类型没有 equals 方法。
  • 引用类型:== 比较对象内存地址,判断是不是同一个对象。

equals:

  • Object 中 equals 默认实现就是比较对象地址。 像 String、Integer 等类重写了 equals,改为比较对象内容是否相等。

应用场景:

  • ==:基本类型判等;判断两个引用是否指向同一个对象。

  • equals:字符串、实体类,比较两个对象业务内容是否一致,调用前最好判空。

6.equals 和 hashCode 的契约是什么?为什么重写 equals 必须重写 hashCode?两个对象 hashCode 相同,equals 一定相同吗?反过来呢?

equals 和 hashCode 的契约是:

  1. 如果两个对象equals相等,那么它们的hashCode必须相等;
  2. 如果两个对象hashCode相等,equals 不一定相等(哈希碰撞);
  3. 对象不变的前提下,多次调用 hashCode 返回值保持一致。

为什么重写 equals 必须重写 hashCode: Object 原生 hashCode 根据对象内存地址生成。只重写 equals 不重写 hashCode,两个 equals 为 true 的对象,hashCode 值会不同。HashSet、HashMap 在判断对象是否重复时,会先对比 hashCode,hashCode 不一样就直接判定是两个对象,最终出现重复存储、查询不到数据的 bug。

两个对象 hashCode 相同,equals 不一定相同(哈希碰撞,不同对象算出一样 hash 值); 反过来,如果 equals 返回 true,hashCode 一定相同(遵守契约)。

应用场景:

​ 重写实体类 equals 时,一定要同步重写 hashCode;对象要放入 HashMap、HashSet 的时候必须遵守这个契约。

作者:bingbing-blog

出处:http://www.cnblogs.com/bingbing-blog/

本文版权归作者和博客园共有,转载必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

posted @ 2026-09-09 09:05  冰冰的blog  阅读(10)  评论(0)    收藏  举报