06、Java 基础硬核复习:面向对象编程(基础)的核心逻辑与面试考点

第一部分:核心知识体系

1. 面向对象思想

  • 面向过程 vs 面向对象:面向过程以“函数”为核心,强调步骤;面向对象以“对象”为核心,强调封装(属性+方法)。
  • OOP 基本元素:类(class,对象的模板)和对象(object,类的实例)。

2. 类的成员与实例化

  • 类的定义:使用 class 关键字定义,包含属性(成员变量)和方法(成员方法)。
  • 类的初始化:通过构造器(constructor)初始化对象,属性可默认初始化(如 int 类型默认为 0)。
  • 匿名对象new Phone().call();,仅使用一次,无需变量引用。
  • 对象内存解析:栈(存储引用变量)+ 堆(存储对象实体),例如 Phone p = new Phone(); 中,p 在栈,Phone 对象在堆。

3. 方法

  • 方法的定义:包含返回值类型、方法名、参数列表、方法体(如 public void call() { ... })。
  • 方法的调用方式:对象调用(p.call())、静态调用(Phone.staticMethod())。
  • 内存分析:方法调用时,栈帧入栈(存储局部变量、操作数栈),方法执行完毕后栈帧出栈。

4. 对象数组

  • 声明与初始化Phone[] phones = new Phone[3];(声明数组)→ 循环 phones[i] = new Phone();(初始化每个元素)。
  • 遍历:使用增强 for 循环(for (Phone p : phones) { ... })或普通 for 循环。

5. 可变参数

  • 语法... 表示可变参数,例如 public void concat(String... strs) { ... }
  • 特点:可变参数必须放在参数列表最后,只能有一个可变参数。

6. 递归方法

  • 定义:方法调用自身(如斐波那契数列 f(n) = f(n-1) + f(n-2))。
  • 关键:必须有明确的结束条件(如 n <= 1 时返回 n),否则栈溢出。

7. 权限修饰符

  • private:仅本类可见(保护属性)。
  • public:任何类可见(公共方法)。
  • protected:同包或子类可见(继承场景)。

8. 构造器

  • 作用:初始化对象(如 Phone() { brand = "华为"; })。
  • 重载:构造器可重载(不同参数列表),默认构造器(无参)由编译器自动生成(若未显式定义)。

9. JavaBean 与 UML 类图

  • JavaBean 规范:无参构造、getter/setter 方法、序列化(Serializable 接口)。
  • UML 类图:用 - 表示 private 属性(如 -name: String),+ 表示 public 方法(如 +getName(): String)。

第二部分:高频面试考点

面向对象的特征有哪些方面,请谈一谈你对它们的理解?

面向对象编程(OOP)主要有四大特征(也有常说三大特征,封装、继承、多态):

  1. 封装 (Encapsulation):
    • 理解: 将对象的状态(属性)和行为(方法)打包在一起,并隐藏内部实现的细节。通过访问控制修饰符(private, public等)控制访问权限,只对外暴露必要的接口。
    • 作用: 保护数据安全,解耦,提高代码复用性。
  2. 继承 (Inheritance):
    • 理解: 子类继承父类的特征和行为,使得子类具有父类的属性和方法。
    • 作用: 减少重复代码,建立类之间的层级关系,是多态的前提。
  3. 多态 (Polymorphism):
    • 理解: 同一个行为具有多个不同表现形式。在Java中主要体现为:父类引用指向子类对象。
    • 实现方式: 方法重载(Overload)和方法重写(Override)。
    • 作用: 提高程序的扩展性和灵活性。
  4. (可选) 抽象 (Abstraction):
    • 理解: 将一类对象的共同特征总结出来构造类的过程,包括数据抽象和行为抽象。

1. 类与对象的内存模型

  • 考点Phone p = new Phone(); 的内存分配过程。
  • 答案:栈中存储 p(引用变量),堆中存储 Phone 对象(包含属性和方法),属性默认初始化(如 brand = null)。

2. 方法的值传递机制

  • 考点:Java 中方法参数是值传递,即使是引用类型,传递的是“引用的副本”。
  • 陷阱:修改引用指向的对象属性会影响原对象(如 p.setBrand("小米")),但修改引用本身(如 p = null)不会影响原对象。

3. 对象数组的初始化陷阱

  • 考点Phone[] phones = new Phone[3]; 后,数组元素是 null,直接调用方法会报 NullPointerException
  • 解决方案:循环初始化每个元素(phones[i] = new Phone();)。

4. 可变参数的注意事项

  • 考点:可变参数只能有一个,且必须放在参数列表最后。
  • 错误示例public void test(int... nums, String str)(编译报错)。

5. 递归的优化

  • 考点:递归可能导致栈溢出,如何优化?
  • 答案:用循环代替递归(如斐波那契数列用 for 循环计算),或尾递归优化(部分 JVM 支持)。

6. 权限修饰符的选择

  • 考点:为什么属性通常用 private
  • 答案:封装(隐藏实现细节),通过 public 的 getter/setter 方法访问,避免直接修改属性导致数据不一致。

7. 构造器的重载

  • 考点:如何根据不同需求提供多个构造器?
  • 示例Phone() { ... }(默认品牌)、Phone(String brand) { this.brand = brand; }(指定品牌)。

8. JavaBean 的规范

  • 考点:为什么 JavaBean 需要 getter/setter
  • 答案:封装(控制属性访问),例如 private String name; 通过 public String getName() { return name; }public void setName(String name) { this.name = name; } 访问。

9. UML 类图的解读

  • 考点:如何从 UML 类图看出类的属性和方法?
  • 示例-age: int 表示 private int age;+eat(): void 表示 public void eat() { ... }

总结

面向对象编程的基础是理解“类”与“对象”的关系,掌握方法的调用、构造器的初始化、内存模型等核心概念。面试中,这些知识点常以“内存分配”“方法传递”“构造器重载”等形式出现,需重点掌握。扎实的基础将为后续学习封装、继承、多态打下坚实基础。