3
class A <T> {

    private T field;
}

我知道我可以使用 < ... extends ... > 将类型参数强制为某种有界类型,但是如何强制类型参数 T 仅为 String、Integer、SomeClassB、SomeEnumC 而不能用其他东西参数化它?

A<SomeClassB> a = new A<SomeClassB>();

会是合法的。

A<SomeClassX> a = new A<SomeClassX>();

将是非法的。

我已经尝试使用

T instanceof SomeEnumC

在类 A 的构造函数中,但它非常混乱。

4

4 回答 4

2

注意:我同意上面@Jeffrey 的评论,这似乎没有多大意义,因为您似乎无法通过这种限制获得任何有用的类型信息。我真的很想知道您的用例在这里。


您不能将可接受的泛型类型限制为T示例中的不相关类列表。您只能使用superor来限制泛型类型extends,这意味着它们必须是某些给定类型的超类型或子类型。

但是,由于您似乎想要允许的类数量有限T,因此您应该能够枚举所有这些类。这就是我的想法:

public class A<T> {

  /**
   * Private constructor means only nested classes
   * can extend this class. We use this to limit the
   * types that can be used for T.
   */
  private A() { }

  /** Integer version of A */
  public static class IntA extends A<Integer> { }

  /** String version of A */
  public static class StringA extends A<String> { }

}

现在您可以使用静态导入来导入您想要的任何嵌套版本A<T>,或者像这样导入所有嵌套版本:import static A.*;

于 2013-11-09T23:19:18.363 回答
1

我假设您想将 A 类导出为 API 的一部分,这就是为什么您要限制可以作为泛型类型参数传递的类型的原因。

如果您想要限制 Class A 的类型列表是已知的(并且数量相当少),那么解决方法是定义一个包私有接口(这将阻止包外部的类实现该接口):

interface A <T> {
    T field;
}

然后,您可以简单地为您希望允许的类型编写具体的类。因为没有其他人可以实现您的接口,所以不可能有人根据您不打算允许的类型编写类。

于 2013-11-10T00:22:23.073 回答
0

我认为您的设计可能存在缺陷,并且更好的设计将完全避免需要这样做。但是,如果您真的想走这条路,请使用私有构造函数和工厂方法:

public class A<T> {
    private T field ;

    private A(T t) {
        this.field = t ;
    }

    public static A<String> getInstance(String s) {
        return new A<String>(s);
    }

    public static A<Integer> getInstance(Integer i) {
        return new A<Integer>(i);
    }

    // etc....

    // regular instance methods...

    public void doStufF() {
        if (field instanceof Integer) { /* ... */ }
        else if (field instanceof String) { /* ... */ }
    }
}

每当您看到丑陋的 if/else 切换类型时,您都应该考虑“丰富的枚举......”,就像在 scottb 的回答之后的讨论中一样。

于 2014-10-22T12:34:03.457 回答
0

您不能在编译时限制它,但稍作调整就可以在运行时强制执行它:

class A <T> {
    private T field;
    public A(Class<T> c) {
        if (c != String.class | c != Integer.class | c != SomeClassB.class | c != SomeClassC.class)
            throw new IllegalArgumentException();
    }
}
于 2013-11-09T23:44:49.647 回答