1403 字
7 分钟
Java 类与对象细节:访问控制、static/final、初始化与 Object

这一篇补充面向对象概念之外的常见基础题:谁能访问成员,成员属于类还是实例,创建对象时先执行什么,以及 Object 提供哪些能力。

四种访问范围#

下面讨论类的成员,不能把这张表直接套到顶层类上。

修饰符同一类同包其他类不同包的子类不同包的普通类
private可以不可以不可以不可以
不写修饰符,即包访问可以可以不可以不可以
protected可以可以可以,但受继承访问规则限制不可以
public可以可以可以可以

跨包子类访问 protected 实例成员时,要遵守接收者类型等限制,不能通过任意父类对象自由访问。基础面试先记住“同包可用,跨包子类通过继承访问”,不用展开所有边界题。

普通顶层类不能声明为 private 或 protected;public 顶层类通常需要与源文件同名。嵌套类的访问修饰规则则不同。

static 与实例成员#

static 字段和方法属于类,实例字段和方法属于对象。准确地说,静态状态与具体类身份关联,不同类加载器定义的同名类可能各自有静态状态。

静态方法没有 this,不能直接访问实例字段或调用实例方法;有明确对象引用时仍可以访问它的实例成员。实例方法可以使用静态成员,但业务上通常通过类名表达静态访问。

静态方法不会像实例方法一样按实际对象类型进行重写分派。子类声明同名同参数静态方法属于隐藏,调用选择取决于编译时的类型信息。static 也不意味着线程安全,多个线程仍可能竞争同一个静态可变字段。

final 分别限制什么?#

用法限制
final 变量赋值后不能重新赋值;引用指向不变不等于对象内容不变
final 方法不能被子类重写
final 类不能被继承

static final 也不一定是编译期常量。例如通过方法计算的值,或指向可变对象的引用,不会因为这两个修饰符就自动具备常量折叠与不可变语义。

final、finally、finalize 是不同概念:final 是语言修饰符,finally 是异常处理中的清理代码块,finalize 是已弃用的历史对象终结方法。不要用 finalize 代替文件或连接的显式关闭。

初始化顺序怎么判断?#

常见继承场景的主线是:父类静态初始化 → 子类静态初始化 → 父类实例初始化与构造器 → 子类实例初始化与构造器。静态初始化通常每个类身份只执行一次,实例初始化每次创建对象都会执行。

class Parent {
static { System.out.println("parent static"); }
{ System.out.println("parent instance"); }
Parent() { System.out.println("parent constructor"); }
}
class Child extends Parent {
static { System.out.println("child static"); }
{ System.out.println("child instance"); }
Child() { System.out.println("child constructor"); }
}
class InitDemo {
public static void main(String[] args) {
new Child();
}
}

首次运行输出:

parent static
child static
parent instance
parent constructor
child instance
child constructor

同一类中的字段初始化表达式和初始化块通常按源代码顺序执行。对象字段在这些显式初始化之前已有默认零值;实例初始化逻辑在父类构造返回后、当前类构造器的剩余主体之前执行。构造器链和静态初始化是两套机制,不要混为一谈。

如果再 new Child,父子类的静态块不会因创建新对象重新执行。访问编译期常量等初始化触发条件,接着读 类加载与初始化。

Object 常用方法#

方法基础用途与追问
getClass获取对象实际运行时类型,和引用声明类型不一定相同
equals默认比较身份,业务类型可重写逻辑相等
hashCode哈希结构使用的哈希值,相等对象必须有相同值;不是保证唯一的地址
toString提供文本表示,常用于日志;输出业务信息时注意敏感字段
clone默认字段级浅拷贝,支持条件和可见性要按类型处理,并非所有对象可直接调用
wait / notify / notifyAll对象监视器上的等待与通知,调用时必须持有对应监视器

equals/hashCode 的完整约定看 相等判断与字符串,等待通知看 线程协作,这里不重复展开。

面试回答模板#

访问修饰符控制成员可见范围,protected 包含同包访问和有条件的跨包继承访问。static 属于类,实例成员属于对象;静态方法没有 this,也不参与实例重写分派。final 限制赋值、重写或继承,不自动保证对象不可变。初始化通常先父类静态、子类静态,再父类实例与构造、子类实例与构造。Object 提供类型、相等、哈希、文本、拷贝和监视器协作等基础能力。

自测#

  1. static 方法能直接使用 this 吗?不能。
  2. static final List 能否添加元素?取决于列表本身,修饰符不禁止内容变化。
  3. 第二次创建 Child,父类静态块会再次执行吗?不会因这次对象创建重新执行。
  4. hashCode 是否保证不同对象都不同?不保证,允许哈希冲突。
Java 类与对象细节:访问控制、static/final、初始化与 Object
https://blog.xqcherry.top/posts/interview/java/java-class-members-and-initialization/
作者
xqcherry
发布于
2026-10-12
许可协议
CC BY-NC-SA 4.0