Java泛型与内部类和内部接口

9

以下是一个通用的OuterClass,它包含使用OuterClass泛型和非泛型InnerInterface的InnerClass。

public class OuterClass<E> {

    public class InnerClass  {

        public E someMethod() {
            return null;
        }
    }

    public interface InnerInterface{
        public void onEvent(OuterClass.InnerClass innerClass);
    }
}

在下面的主方法中,我使用了两个OuterClass的实例,o1用<>参数化,o2用<>参数化。 我的匿名内部类 myListener 尝试使用外部类(E)的通用类型。 如下所示的代码无法编译(Integer i = innerClass.someMethod() - 类型不匹配:无法将Object转换为Integer)。
public class Test {
    public static void main(String[] args) {

        OuterClass<Integer> o1 = new OuterClass<Integer>();
        OuterClass<String> o2 = new OuterClass<String>();

        OuterClass.InnerInterface innerInterface = new OuterClass.InnerInterface() {
            @Override
            public void onEvent(InnerClass innerClass) {
                Integer i = innerClass.someMethod();
            }
        };
    }
}

我想表达的是,myListener 是给 o1 用的,应该使用 E = Integer,而不需要重复声明(因为在声明 o1 的时候已经声明过了)。这种情况是否可行?

非常感谢! Faton。


你的接口方法也需要泛型化。 - Bombe
2个回答

16

内部接口或枚举类型是隐式静态的,并且静态成员不会使用外部类的类型参数进行参数化。因此,InnerInterface 应该如下所示:

public interface InnerInterface<E> {
    void onEvent(OuterClass<E>.InnerClass innerClass);
}

请注意,InnerInterfaceE参数与OuterClassE参数不是相同的。


8
也许,那么,最好不要称它为E? - Ingo
2
谢谢Laurent。这会起作用,但我必须重复<Integer>,因为它是不同的E。我的问题是“是否可以重用第一个E = <Integer>”,并且防止为接口重新声明<Integer>? - Faton
1
最好不要使用相同的标识符作为泛型参数。 - Tom Hawtin - tackline
@Faton 那么答案是否定的。 - Laurent Pireyn
@Tom 或许吧,但是 InnerInterface 的类型参数与 Outerclass 中的 E 具有完全相同的含义,我认为使用相同的名称可以使这种关系更加明显。 - Laurent Pireyn
@Laurent Pireyn,就代码而言,它是完全独立的。如果它们没有交叉作用域(明智),那么这就不是问题。 - Tom Hawtin - tackline

1

一如既往,非private嵌套类型并不能帮助保持简单。尽管你的IDE可能会反对,但是大胆创造一些新文件。

无论如何,类的静态成员不共享外部类的通用参数。这对于字段的行为非常重要,并且即使您不想要它,也允许更多关于静态嵌套类型(例如InnerInterface)的灵活性。因此,在您的情况下,您需要给您的(静态)嵌套接口一个通用参数。求求您了,请使用不同的标识符!

public class OuterClass<E> {
    public class InnerClass  {
        public E someMethod() {
            return null;
        }
    }

    public interface InnerInterface<T> {
        void onEvent(OuterClass<T>.InnerClass innerClass);
    }
}


public class Test {
    public static void main(String[] args) {

        OuterClass<Integer> o1 = new OuterClass<Integer>();
        OuterClass<String> o2 = new OuterClass<String>();

        OuterClass.InnerInterface<Integer> innerInterface =
            new OuterClass.InnerInterface<Integer>() 
       {
            @Override
            public void onEvent(OuterClass<Integer>.InnerClass innerClass) {
                Integer i = innerClass.someMethod();
            }
        };
    }
}

在必要时,我还对InnerClass进行了限定。

编辑:从其余用途中分离出来,仅查看原始的匿名内部类可能是值得的:

public interface InnerInterface{
    public void onEvent(OuterClass.InnerClass innerClass);
}

    OuterClass.InnerInterface innerInterface = new OuterClass.InnerInterface() {
        @Override
        public void onEvent(InnerClass innerClass) {
            Integer i = innerClass.someMethod();
        }
    };

Integer 只出现了一次,而且在一个明显无法推断其正确性的地方。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接