新列表<a &="" ?="" extends="" b="">();

时间:2018-04-27 13:22:53

标签: java generics interface abstract-class

If you know how to run the title line, just scroll down to tl;dr or write an answer!

I wrote the rest of the text to avoid the XY problem。完成后就不再重要了。

上下文

我想创建一个采用泛型(List,Map等)的对象。

列表中的对象应该满足2个标准:

  1. mymethod()(我通过创建一个以此为方法头的界面来实现)
  2. 扩展JComponent
  3. 我是如何尝试这项工作的:

    1. 我创建了多个类,其中任何一个都在实现MyInterface并且正在扩展JComponent(它的子类)。这就是我在标题问题中运行的地方:new List<MyInterface extends JComponent);
    2. 另一个想法:创建一个抽象类(符合所有条件)而不是接口。问题:我需要的具体类不会扩展同一个类。
    3. 我想到了泛型,就像:public abstract class MyClass<X extends JComponent> extends X一样,但由于显而易见的原因,这不起作用。 (例如,我必须从超类中实现抽象方法,但如果它是Generic,我现在还不知道。)
    4. TL;博士

      我遇到了一个问题,如果你可以让这条线路正常工作,那么很容易就会出现这个问题:

      new List<A extends B>();
      

      或由@khelwood介绍:     新List();

      其中:

      • A是一个界面(就像我可以声明new List<MyInterface>()
      • 一样
      • 和任何项扩展? extends B(例如:它可以是JTextField或JTextArea或他们喜欢的任何内容,但它必须是(子类)JComponent (JComponent = B ))

3 个答案:

答案 0 :(得分:1)

如果您希望能够创建扩展JComponent并实现接口的内容列表,并将内容添加到此类列表中,则需要定义实现这两者的具体类型:

List<ThatType> list = new ArrayList<>();
list.add(new ThatType());

您可以为此声明一个类型变量,以便编写泛型方法:

<T extends JComponent & YourInterface> void something(T thing) {
  // ...
}

<Something extends SomethingElse>仅适用于类型变量的声明。

此外,您不会创建Somethings that extends SomethingElse列表:您创建Somethings列表,Something extends SomethingElse是否取决于这些类型的定义。

为了使其更加具体,您不要制作new List<String extends Object>:您制作List<String>,而String恰好延伸Object

您需要适当地声明类型变量,例如:

class Foo<B> {
  <A extends B> List<A> list() {
    return new List<>();
  }
}

答案 1 :(得分:0)

你这么说:

  

另一个想法:创建一个抽象类(符合所有条件)而不是接口。问题:我需要的具体类不会扩展同一个类。

但与此同时你说他们延长了JComponent。发生这种情况的唯一可能性是它们都可以传递JComponent。因此,在某种程度上,继承层次结构存在来自JComponent的直接继承。

如果这仍然是您的代码,那么您可以引入另一个类,而不是扩展JComponent并实现您的界面的JComponent

如果没有,那么我认为仅使用语法就无法实现。

答案 2 :(得分:0)

我不认为类型系统允许您完全按照自己的意愿行事并获得编译时类型的安全性。

一个近似值如下:

List<JComponent> componentList = new ArrayList<>();
List<MyInterface> myInterfaceList = (List) componentList;

如果你不介意编译时警告,你现在在同一个列表上有两个视图:一个显示内容为JComponent,另一个显示为MyInterface。< / p>

您可以将对象添加到任一视图,然后从为上下文提供正确类型的视图中读取它们。

当然,当你添加一个对象时,编译器将检查插入的对象是否为JComponentMyInterface的子类。这是你的责任。

如果你想要更多(运行时)类型安全,你可以这样:

List rawList = new ArrayList();
List checkedList = Collections.checkedList(rawList, JComponent.class);
List doublyCheckedList = Collections.checkedList(checkedList, MyInterface.class);
List<JComponent> componentList = doublyCheckedList;
List<MyInterface> myInterfaceList = doublyCheckedList;

如果只插入doublyCheckedList,则在运行时列表将检查插入的对象是否为JComponentMyInterface的子类。阅读时,您可以使用我之前片段中的两个视图。