protected不能直接实现跨包安全提取父类资产,其本质是受控可访问性:子类仅能通过继承关系(如this.xxx或super.xxx)访问,不可通过父类对象引用跨包访问;需配合getter、抽象方法或不可变视图等封装手段达成目标。

protected 的真实访问规则
protected 成员对子类可见,但仅限于“通过继承关系”访问,不是“通过引用访问”。这意味着:
- 子类(无论是否同包)可以自由调用
super.xxx()或直接使用this.xxx(若为实例成员); - 子类对象在 其他类中(即使是子类自己的静态方法或同一包内代码)不能通过对象引用访问父类的 protected 成员,例如
parentObj.protectedField在跨包时编译失败; - 同包非子类可以访问本包内任何类的 protected 成员(这是 protected 区别于 private 的宽松之处,但与继承无关)。
实现“跨包安全提取”的可行路径
若目标是让子类在不同包中安全获取父类的某些内部数据,应结合 protected + 封装接口,而非依赖修饰符单独完成:
-
将需暴露的资产设为 protected,并提供受控的 getter 方法:父类中声明
protected String sensitiveData;,同时定义protected final String getSensitiveData() { return this.sensitiveData; }。子类可安全调用该方法,且无法意外修改原字段; -
用 protected 抽象方法强制子类参与处理逻辑:如父类定义
protected abstract void onAssetReady(Object asset);,子类在重写中决定如何“提取”或响应,资产本身由父类内部管理、按需传递; -
避免直接暴露字段,优先暴露不可变视图:例如返回
Collections.unmodifiableList(protectedList),既利用 protected 让子类能拿到原始引用,又通过包装防止外部篡改。
常见误区与规避建议
开发者常误以为 “protected = 跨包子类可任意访问父类所有 protected 成员”,实际限制更多:
- 子类不能访问父类对象的 protected 成员(除非是 自身继承链上的实例),所以不要写
Parent p = new Parent(); p.protectedField = ...—— 这在跨包时非法; - 如果需要子类“读取但不继承”,考虑 package-private(默认)+ 同包工厂类,或引入模块化(Java 9+)的
opens指令,而非强行用 protected 打破封装; - 敏感资产若需严格管控,protected 仍不够,应搭配权限检查(如 SecurityManager)、运行时断言或专用访问器(AccessController.doPrivileged)。











