【问题标题】:Java generics with inner class and inner interface具有内部类和内部接口的 Java 泛型
【发布时间】:2011-03-23 09:04:39
【问题描述】:

下面我有一个通用的 OuterClass,一个使用 OuterClass 泛型的 InnerClass 和 非泛型内部接口。

public class OuterClass<E> {

    public class InnerClass  {

        public E someMethod() {
            return null;
        }
    }

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

在下面的 main 方法中,我使用了 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的时候已经说过了)。这可能吗?

非常感谢! 法顿。

【问题讨论】:

  • 你的接口方法也需要泛化。

标签: java generics


【解决方案1】:

内部接口或枚举是隐式静态的,静态成员不使用外部类的类型参数进行参数化。所以InnerInterface 应该是这样的:

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

注意InnerInterfaceE 参数OuterClassE 参数相同。

【讨论】:

  • 或许,不叫E比较好?
  • 谢谢劳伦特。它会起作用,但我必须重复 因为它是一个不同的 E。我的问题是“是否可以重用第一个 E = ”,并防止为接口重新声明
  • 对通用参数使用相同的标识符可能不是一个好主意。
  • @Faton 那么答案是否定的。
  • @Tom Maybe,但InnerInterface 的类型参数与OuterclassE 具有非常相同的含义,我认为使用相同的名称会使这种关系显而易见。
【解决方案2】:

与往常一样,非private 嵌套类型无助于保持简单。即使您的 IDe 对您不利,也可以将船推出并创建一些新文件。

无论如何,类的静态成员不共享外部类的通用参数。这对于字段的行为很重要,并且即使您不想要它也允许静态嵌套类型(例如InnerInterface)具有更大的灵活性。因此,在您的情况下,您需要为(静态)嵌套接口提供一个通用参数。看在 $deity 的份上,请使用不同的标识符!

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 只出现一次,出现在明显无法推断其正确的地方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多