Java泛型 - 从方法返回声明类型的子类型

6 java generics

我的类正在实现一个返回的超类方法List<JComponent>.返回的列表是只读的:

public abstract class SuperClass {
    public abstract List<JComponent> getComponents();
}
Run Code Online (Sandbox Code Playgroud)

在我的课堂上,我想返回一个声明为List的字段 - 即一个子列表:

public class SubClass extends SuperClass {
    private List<JButton> buttons;
    public List<JComponent> getComponents() {
        return buttons;
    }
}
Run Code Online (Sandbox Code Playgroud)

这会生成编译器错误,因为List<JButton>它不是子类型List<JComponent>.

我可以理解它为什么不编译,因为不应该允许将JTextField添加到JButton列表中.

但是,由于列表是只读的,因此应该允许"概念上".但是,当然,编译器不知道它是只读的.

有没有办法实现我想要实现的目标,而无需更改超类中的方法声明,以及子类中的字段声明?

谢谢,卡鲁姆

Ada*_*eld 10

声明getComponents()为:

public List<? extends JComponent> getComponents()
Run Code Online (Sandbox Code Playgroud)

  • 我给了你+1,但请注意,通常将 ? 表达式放在返回值中是不好的形式,因为它要求调用者效仿。也就是说,这不会编译:List&lt;JComponent&gt; foo = obj.getComponents()。 (2认同)
  • "相反,调用者还必须将其列表声明为List <?extends JComponent>,依此类推.Yukky." 但是呼叫者无论如何都是这样做的好习惯.由于调用者没有向列表中添加任何元素(OP表示它是只读的),调用者不应该关心列表的实际参数,只要它扩展JComponent即可.对于抽象,调用者应该使用他/她需要的限制最少的类型. (2认同)

小智 6

我想我找到了我正在寻找的答案......

return Collections.<JComponent>unmodifiableList(buttons);
Run Code Online (Sandbox Code Playgroud)

我曾经尝试过:

return Collections.unmodifiableList(buttons);
Run Code Online (Sandbox Code Playgroud)

但这是类型推断的List<JButton>.

放入显式类型参数允许将List<JButton>其视为a List<JComponent>,这是允许的unmodifiableList().

我现在很开心;-)而且我已经通过讨论学到了一些东西.

Calum