java - 使用一组固定类型中的一个来参数化一个类

标签 java class generics java-8

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

为了说明,假设我希望 Foo 保存 StringInteger 。最低的公共(public)上限是 Object ,因此指定上限不会奏效。

当然,我可以按照以下方式做一些事情

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 的东西来实例化它,我将在运行时得到一个异常。

我想做得更好。我希望编译器静态推断(即,在编译时)我只能使用 StringInteger 的对象实例化此类。

我在想沿着这些思路做的事情可能会成功:

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 的后一个定义,我可以这样做,例如:

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

当然这里的类型参数应该是String,而不是Character。但是编译器让我摆脱了上述分配。

  1. 有没有办法实现我想要的,如果有,怎么做?
  2. 附带问题:为什么编译器允许我对上面类型为 Foo<Character> 的对象进行赋值,甚至连 警告 都没有(在使用类 Foo 的后一个定义时)? :)

最佳答案

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

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;
    }
}

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

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

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

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

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

Foo<Character> fooc2;

Foo<Character> fooc3 = null;

Foo<Object> fooob1;

Foo<Object> fooob2 = null;

关于java - 使用一组固定类型中的一个来参数化一个类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48993454/

相关文章:

java - 连接 "computer-database-jpa"Play 2.1 示例应用程序与 MySQL

java - Maven maven-resources-plugin 复制目标 jar

c# - 类属性默认值(如果未分配)

java - Struts 2,tomcat 7 上的 "Resourse not found",jdk 1.7

javascript - 在 es6 中克隆一个类

c++ - 返回在非类型模板化类中定义的 typedef

ios - Swift 4 - 通用类型转换问题 - 无法转换为预期类型 '(_) -> Void'

c# - 使用相同类型的类定义 where 关键字

C++ 模板 - 具有模板化类型的通用方法

java - 使用导入范围功能下载文件时出错