Java中抽象类的protected字段访问规则由语言规范固定:同包内任意类可直接访问;同包子类可通过this或实例访问;跨包子类仅能通过this或super访问继承字段;static protected字段跨包可通过类名访问;非子类跨包完全不可见。

Java中抽象类里的protected字段,访问规则不靠“配置”,而是由语言规范固定——它和普通类中的protected字段完全一致,只取决于包结构和继承关系,无需额外声明或设置。
同包内任意类都能直接访问
只要在同一个包下,无论是否继承抽象类,也不管访问者是普通类、工具类还是另一个抽象类,都可以通过实例直接读写该protected字段。
- 例如:抽象类
Animal在com.zoo包中声明protected String name; - 同包下的
ZooHelper类可写:new Animal().name = "Lion";(合法) - 这种访问方式与
default权限效果相同,但语义上强调“有意开放给协作类”
子类访问分同包和跨包两种情况
子类能否访问,关键看它和抽象父类是否在同一个包:
-
同包子类:可直接使用
this.name,也可通过new Animal().name访问(不限调用主体) -
跨包子类:只能访问自己继承来的字段,即
this.name或super.name;不能写new Animal().name,否则编译报错 - 注意:即使子类重写了方法或添加了新字段,只要继承关系存在,继承来的
protected字段仍可被子类代码直接使用
static protected 字段更宽松
如果字段同时被static和protected修饰,跨包子类可通过类名直接访问,不受“必须用子类实例”的限制:
立即学习“Java免费学习笔记(深入)”;
- 抽象类中:
protected static int COUNT = 0; - 跨包子类中:
Animal.COUNT++或this.COUNT都合法 - 本质是静态成员属于类本身,编译器只检查访问者是否为子类,不校验调用表达式类型
非子类跨包一律不可见
如果一个类既不在抽象类的包内,也没有继承关系,那它对protected字段完全不可见:
- 哪怕导入了抽象类、用了反射,
getDeclaredField("name")也会在运行时抛IllegalAccessException - 编译阶段就拒绝:
new Animal().name直接报错:“has protected access” - 这和
default形成对比:后者连同包子类都拦住,而protected至少保留了跨包子类的通道


















