Infra SWE · Phone Java Fundamentals

LinkedIn Java Object 与 Inner Class:外部实例引用及生命周期

区分 Object 基类、非静态内部类、静态嵌套类,解释构造、捕获外部实例与意外内存保留。

题目重点:区分 Object 基类、非静态内部类、静态嵌套类,解释构造、捕获外部实例与意外内存保留。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 以下采用 Java 常见语义;Object 指 java.lang.Object,inner class 指成员内部类,另把 static nested class 作为对照。局部类和匿名类仅作追问。

解题路线

  1. 所有普通引用类直接或间接继承 Object,因此可使用 equals/hashCode/toString 等方法;但 Object 类型的引用只暴露声明类型上的成员,访问子类独有方法需安全类型检查和转换。重写 equals 时必须保持自反、对称、传递与 hashCode 契约。
  2. 非静态成员内部类每个实例关联一个外部类实例,可访问外部实例成员;在外部类实例方法里 new Inner(),在外部需 outer.new Inner()。这个关联会延长 outer 的可达生命周期,若把 inner 交给长寿命线程/回调,需评估无意持有。
  3. 静态嵌套类没有隐含 outer 实例,通常用 new Outer.Nested() 创建;只能直接访问外部类静态成员,要访问实例状态则显式传入 outer。若无需外部实例,优先用静态嵌套类降低耦合。
  4. 并发上,inner 能访问 outer 字段不等于自动线程安全;可见性与互斥仍需按共享状态设计。对象回收取决于可达性,不能简单说内部类必然泄漏。

手动走一遍

假设 Outer 有 int count=1,成员内部类 Inner 的 read() 返回 count;Outer o=new Outer(); Outer.Inner i=o.new Inner(); 返回 1。把 Inner 改成 static 后,read() 不再能直接读 count,必须构造时显式传入 Outer 或数值。若某全局回调表长期保存 i,也可能同时保留 o。

规模与取舍

这是语言语义和引用生命周期题,无统一的算法时间复杂度;一次字段读取近常数时间,实际对象大小、额外引用与垃圾回收成本依 JVM 实现,不能从题名推出字节数。

易错点与追问

容易失分的边界

  • 把 java.lang.Object 与任意对象实例混为同一概念。
  • 认为静态嵌套类会隐式捕获外部实例。
  • 把内部类访问外部字段误当线程安全。
  • 断言所有内部类实例必然内存泄漏。
  • 覆盖 equals 却遗漏 hashCode。

继续深挖

  • 匿名类、lambda 和成员内部类捕获方式有何不同?
  • 什么时候用静态嵌套类?
  • 长寿命 listener 持有 inner 有何影响?
  • Object.equals 与 hashCode 的契约是什么?
✓已复制微信号!