如何让内部类复用外部类泛型参数?附Java代码示例
嘿,针对你的两个问题,我来给你详细拆解下,再结合你写的代码说说具体情况:
问题1:是否可以声明内部类与外部类使用相同的泛型类型?
答案是可以,但非常不推荐。
语法上Java允许你给内部类声明和外部类同名的泛型参数(比如都用<L,R>),但这时候内部类的泛型参数会遮蔽外部类的同名泛型——简单说,内部类里的L和R是完全独立的新类型参数,和外部类的L、R没有任何关系。这种写法不仅没用,还会造成代码混淆,让阅读者误以为两者有关联,所以实际开发中绝对不要这么做。
举个反例:
public class Outer<L, R> { // 内部类声明了和外部类同名的泛型,会遮蔽外部类的泛型 class Inner<L, R> { void printType(L obj) { // 这里的L是Inner自己的泛型,不是Outer的L System.out.println(obj.getClass()); } } }
问题2:是否可以让内部类复用外部类的泛型参数?
当然可以!而且这才是内部类使用外部类泛型的正确姿势,分两种情况:
情况1:非静态内部类
非静态内部类默认持有外部类实例的引用,所以可以直接复用外部类的泛型参数,不需要自己额外声明。
回到你的代码,如果TaggedUnion是TaggedUnionBuilder的非静态内部类,你完全可以去掉它自己的泛型声明,直接用外部类的L和R:
public class TaggedUnionBuilder<L,R>{ private final Class<L> leftClass; private final Class<R> rightClass; public TaggedUnionBuilder(Class<L> leftClass, Class<R> rightClass) { this.leftClass = leftClass; this.rightClass = rightClass; } TaggedUnion left(L aLeft){ return new TaggedUnion(true, aLeft); } TaggedUnion right(R aRight){ return new TaggedUnion(false, aRight); } // 非静态内部类,直接复用外部类的L、R class TaggedUnion { private final boolean isLeft; private final Object value; TaggedUnion(boolean isLeft, Object value) { this.isLeft = isLeft; this.value = value; } // 用外部类的Class对象做安全类型转换 L getLeft() { if (!isLeft) throw new IllegalStateException("Not a left value"); return leftClass.cast(value); } R getRight() { if (isLeft) throw new IllegalStateException("Not a right value"); return rightClass.cast(value); } } }
情况2:静态内部类
静态内部类不持有外部类的实例引用,所以无法直接访问外部类的泛型参数。这时候你可以给静态内部类自己声明泛型参数,或者在实例化时传递外部类的泛型类型(不过本质上还是独立的泛型):
public class TaggedUnionBuilder<L,R>{ // ... 其他代码不变 ... // 静态内部类需要自己声明泛型参数 static class TaggedUnion<L, R> { private final boolean isLeft; private final Object value; TaggedUnion(boolean isLeft, Object value) { this.isLeft = isLeft; this.value = value; } // 这里需要额外传入Class对象做类型转换,因为静态内部类拿不到外部类的leftClass/rightClass L getLeft(Class<L> leftClass) { if (!isLeft) throw new IllegalStateException(); return leftClass.cast(value); } } }
总结
- 内部类可以和外部类用相同的泛型类型名,但会遮蔽外部类泛型,不建议使用;
- 非静态内部类可以直接复用外部类的泛型参数,这是最常用的方式;
- 静态内部类需要自己声明泛型参数,无法直接复用外部类的泛型。
内容的提问来源于stack exchange,提问作者Sled
相关产品推荐
相关产品推荐

