使用一组固定类型对类进行参数化 [英] Parameterize a class with one of a fixed set of types

查看:162
本文介绍了使用一组固定类型对类进行参数化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个泛型类 Foo ,它可以容纳 T 类型的对象。此外,假设我希望能够使用两种类型之一的对象来实例化该类。最后,假设这两种类型的最低公共上限是一个类型,它比我想要允许的那两种类型有更多的子类,所以我不能简单地指定类型参数的上限(如 class Foo< T extends Something> ),因为那时我将允许使用除我期望的其他类型来实例化类。

Say I have a generic class Foo which can hold an object of type T. Furthermore, let's say I only want to be able to instantiate the class with objects that are one of two types. Finally, let's say that the lowest common upper bound of these two types is a type that has many more subclasses than those two types that I want to allow, so I can't simply specify an upper bound for the type parameter (as in class Foo<T extends Something>), because then I would allow to instantiate the class with other types than the two I expect.

为了说明,假设我想要 Foo 只能 c>字符串或整数。最低的公共上限是 Object ,所以指定一个上限将不起作用。

For illustration, let's say I want Foo to hold only either a String or an Integer. The lowest common upper bound is Object, so specifying an upper bound won't do the trick.

当然,我可以做的事情

class Foo<T> {

    private T obj;

    public Foo(T obj) throws IllegalArgumentException {
        if (!(obj instanceof String || obj instanceof Integer)) {
            throw new IllegalArgumentException("...");
        }
        this.obj = obj;
    }
}

但是,在这种情况下,我仍然可以调用带有任何对象的构造函数;如果我试图用既不是 String 也不是 Integer 的东西来实例化它,我会在运行时

However, in this case, I can still call the constructor with any object; if I try to instantiate it with something that is neither a String nor an Integer, I will get an exception at runtime.

我想做得更好。我希望编译器静态推断(即,在编译时),我只能使用 String 或<的对象来实例化该类。 code>整数。

I would like to do better. I would like the compiler to infer statically (i.e., at compile time) that I can only instantiate this class with objects that are either String or Integer.

我在想这些行可能会有什么办法:

I was thinking something along those lines might do the trick:

class Foo<T> {

    private T obj;

    public Foo(String s) {
        this((T) s);
    }

    public Foo(Integer i) {
        this((T) i);
    }

    private Foo(T obj) {
        this.obj = obj;
    }
}

这样可行,但看起来真的很奇怪。编译器警告(可以理解)未经检查的强制转换。当然我可以压制这些警告,但我觉得这不是要走的路。此外,看起来编译器实际上推断类型 T 。我很惊讶地发现,使用后者定义的类 Foo ,我可以这样做,例如:

This works, but it looks really, really odd. The compiler warns (understandably) about unchecked casts. Of course I could suppress those warnings, but I feel this is not the way to go. In addition, it looks like the compiler can't actually infer the type T. I was surprised to find that, with the latter definition of class Foo, I could do this, for instance:

Foo<Character> foo = new Foo<>("hello");

当然,type参数应为 String 这里,不是字符。但编译器让我逃脱了上述任务。

Of course, the type parameter should be String here, not Character. But the compiler lets me get away with the above assignment.


  1. 有没有办法实现我想要的,如果有,怎么样?

  2. 附带问题:为什么编译器让我无法完成对上面类型为 Foo< Character> 的对象的赋值一个警告(当使用后一个类 Foo 的定义时)? :)

  1. Is there a way to achieve what I want, and if yes, how?
  2. Side question: why does the compiler let me get away with the assignment to an object of type Foo<Character> above without even so much as a warning (when using the latter definition of class Foo)? :)


推荐答案

尝试使用 static 工厂方法以防止编译器警告。

Try using static factory method to prevent compiler warning.

class Foo<T> {

    private T obj;

    public static Foo<String> of(String s) {
        return new Foo<>(s);
    }

    public static Foo<Integer> of(Integer i) {
        return new Foo<>(i);
    }

    private Foo(T obj) {
        this.obj = obj;
    }
}

现在使用以下方式创建实例:

Now you create instance using:

Foo<String> foos = Foo.of("hello");

Foo<Integer> fooi = Foo.of(42);

Foo<Character> fooc = Foo.of('a'); // Compile error

但是以下内容仍然有效,因为您可以声明任何类型T的Foo,但不实例化它:

However the following are still valid since you can declare a Foo of any type T, but not instantiate it:

Foo<Character> fooc2;

Foo<Character> fooc3 = null;

Foo<Object> fooob1;

Foo<Object> fooob2 = null;

这篇关于使用一组固定类型对类进行参数化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆