繁体   English   中英

带有擦除的Java类型推断

[英]Java type inference with erasure

在擦除和类型推断方面遇到一些问题。 我有以下的类层次结构,看起来并不十分复杂:

public class Foo<T> {

}

public class Bar<T> {
    private final Class<T> clazz;

    public Bar(Class<T> clazz) {
        this.clazz = clazz;
    }
}

我想做的是这样的:

Bar<Foo<?>> bar = new Bar<>(Foo.class);

这当然是行不通的,因为Foo并不是Foo<?> 问题是如何建立这样的酒吧? 我确实需要Bar<Foo<?>> ,而不是Bar<Foo> ,因为有些方法只接受Bar<Foo<?>>作为参数。 欣赏想法。

抱歉,没有这样的Class对象,因为正如您所指出的,擦除意味着不可能。 您需要强制转换:

((Class<Foo<?>>)(Class)Foo.class)

这将为您提供所需的界限,但可能会产生编译器警告,因为您正在执行未经检查的泛型转换。 这是合理的:编译器要求您确认您遗漏了泛型的编译时安全性。 但是在这种情况下,实际上在这种情况下,无论是在您的程序中还是在将来,这种情况都不会产生运行时错误,所以很好。

双播是必要的,因为编译器知道Foo.class与Class>不兼容,因此您必须首先将其转换为“原始”类型Class:在表达式中使用原始类型会禁用编译器的泛型检查这样的表达方式,那么“不可能”的转换就可以了。

如问题帖所示,如果不在<>提供类型信息,就无法创建通用对象。 您必须提供Type或使用原始版本。 如果您被迫使用通配符参数类型,则只需使用原始类型抑制警告,如下所示

@SuppressWarnings("rawtypes")
Bar<Foo<?>> bar = new Bar(Foo.class);       

//Bar is having no type "<>" (but this is not recommended

由于java.lang.Class是不可变的,因此可以在Bar的构造函数中使用较弱的类型声明:

class Foo<T> {}

class Bar<T> {
    private final Class<? extends T> clazz;

    public Bar(Class<? extends T> clazz) {
        this.clazz = clazz;
    }
}

如果您仍然需要该字段的类型为Class<T>而不是Class<? extends T> Class<? extends T> ,将其强制转换为构造函数是安全的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM