如何在不同包的类中创建Java受保护嵌套类的列表?
实现方案
方案一:反射实现(突破访问权限)
反射可以绕过Java的访问控制机制,直接获取受保护嵌套类的Class对象,进而创建对应类型的列表。由于泛型在运行时会被擦除,创建列表时需要进行类型强转。
原类定义(不可修改)
package pkg1; public class SomeClass { protected class Nested { // 嵌套类成员 } }
另一个包的MyClass实现
package pkg2; import pkg1.SomeClass; import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.List; @SuppressWarnings("unchecked") public class MyClass { public void createNestedList() throws Exception { // 获取Nested类的Class对象 Class<?> nestedClass = Class.forName("pkg1.SomeClass$Nested"); // 创建泛型列表(泛型擦除后强转) List<SomeClass.Nested> nestedList = (List<SomeClass.Nested>) new ArrayList<>(); // 若需创建Nested实例并加入列表,同样通过反射 Constructor<?> constructor = nestedClass.getDeclaredConstructor(SomeClass.class); constructor.setAccessible(true); // 解除访问限制 SomeClass outerInstance = new SomeClass(); SomeClass.Nested nestedInstance = (SomeClass.Nested) constructor.newInstance(outerInstance); nestedList.add(nestedInstance); System.out.println("列表元素数:" + nestedList.size()); } }
注意:反射会破坏封装性,且存在一定性能开销,强转时的unchecked警告可通过@SuppressWarnings("unchecked")消除。
方案二:子类中转(符合封装原则)
通过创建SomeClass的子类,利用子类对父类protected成员的访问权限,将Nested类的类型暴露出来,无需使用反射。
创建SomeClass的子类
package pkg2; import pkg1.SomeClass; public class SomeClassSub extends SomeClass { // 暴露Nested类的Class对象 public Class<Nested> getNestedClass() { return Nested.class; } // 提供创建Nested实例的方法 public Nested createNested() { return new Nested(); } }
MyClass中使用子类创建列表
package pkg2; import java.util.ArrayList; import java.util.List; public class MyClass { public void createNestedList() { SomeClassSub subInstance = new SomeClassSub(); // 直接使用子类可访问的Nested类型定义列表 List<SomeClassSub.Nested> nestedList = new ArrayList<>(); // 添加实例 SomeClassSub.Nested nested = subInstance.createNested(); nestedList.add(nested); System.out.println("列表元素数:" + nestedList.size()); } }
关于类似C++ decltype的泛型推导
Java没有直接对应C++ decltype的类型推导语法,但可通过子类继承、方法返回值等方式间接获取受保护嵌套类的类型,方案二就是这类思路的实践。
内容的提问来源于stack exchange,提问作者asdru
相关产品推荐
相关产品推荐

