泛型不只一种类型

时间:2019-08-05 13:12:30

标签: java java-6

为变量分配一个对象,该对象可以扩展类并同时实现一个Interface。 我有这样的方法

public static <T extends Component & MyInterface> T instance() {
  if (test1) return new MyLabel();
  if (test2) return new MyCombo();
  if (test3) return new MyText();
}

class MyLabel extends JLabel implements MyInterface {
  ...
}

class MyCombo extends JComboBox implements MyInterface {
  ...
}

class MyText extends JTextField implements MyInterface {
  ...
}

这意味着instance()返回的对象是Component并实现MyInterface。 我可以做类似的事情

instance.setEnable(true); // calling a Component method
instance.foo();           // calling a MyInterface method

现在,我想将返回的值分配给变量:如何声明该变量以便将所有泛型信息带入该变量?

我希望能够做这样的事情:

static <T extends Component & MyInterface> T myVar = instance();
myVar.setEnable(true); // calling a Component method
myVar.foo();           // calling a MyInterface method

还有这个:

static void f1(Component c) {}
static void f2(MyInterface c) {}
f1(myVar);
f2(myVar);

我认为问题与Why can't I use a type argument in a type parameter with multiple bounds?中的问题不同,因为我没有在泛型类声明中使用类型参数。

2 个答案:

答案 0 :(得分:1)

基于John Bollinger的建议,我进行了一些其他实验,并找到了可能的“解决方案”(但是并不像我要求的那么简单)。 但是我认为我的wrap()方法与John的意思不同。

public final class Wrap<X extends Component & MyInterface> {
    public final X x;
    public Wrap(X x) {
        this.x = x;
    }
}
public static <X extends Component & MyInterface> Wrap<X> wrap(X x) {
    return new Wrap<X>(x);
}

static Wrap<?> myVar = wrap(instance());
myVar.x.setEnabled(true);    // Component method
f1(myVar.x);                 // Component parameter
myVar.x.foo();               // MyInterface method
f2(myVar.x);                 // MyInterface parameter

答案 1 :(得分:0)

  

我希望能够做这样的事情:

static <T extends Component & MyInterface> T myVar = instance();
myVar.setEnable(true); // calling a Component method
myVar.foo();           // calling a MyInterface method

恐怕不是。 Java不提供泛型变量,并且在大多数情况下这样做是没有意义的。您可以将 instance 变量的类型声明为其类的类型参数,但不能像方法一样为任何变量提供其自己的独立类型参数。无法声明具有两种类型的变量。

如示例所示,如果您希望能够同时使用myVar的两个方面,则必须将其类型声明为扩展或实现这两个方面的 specific 类型超类型。有两种主要选择:

  1. 使instance()方法返回这种类型。这可能是最自然的解决方案,因为除挂起超型以外,该方法不依赖于T出于任何其他目的。

    public class MyInterfaceComponent extends Component implements MyInterface {
        // ...
    }
    
    MyInterfaceComponent myVar = instance();
    
  2. 动态生成这种类型的包装对象,该包装对象将适应用于扩展类并实现接口的通用对象。

    MyInterfaceComponent myVar = wrap(instance());
    

只有当您有可能需要处理扩展类并实现接口但无法控制其特定类的外部提供的对象时,后者对我才有意义。