2015-11-12 85 views
2

擦除&类型推理存在一些问题。我有以下的类层次结构,看起来并不很复杂:Java擦除类型推理

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?我只需要Bar<Foo<?>>,而不是Bar<Foo>,因为有方法只接受Bar<Foo<?>>作为参数。欣赏想法。

+1

您可以将'Foo.class'强制转换为'Class >',这可能会为您的目的对这个问题进行充分的论证。 (你不能仅仅用'Class'对象来代表不同的泛型。) –

回答

1

如无法提供<>中的类型信息,您不能创建通用对象,如问题所示。您必须提供一个类型或使用原始版本。如果你被迫使用通配符参数类型,那么就使用原始类型抑制警告,如下图所示

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

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

没错,我最初并没有得到你的答案。这与更复杂的建议一样正确。 –

+1

这是一个选项,我假设。想知道为什么我没有自己试试:) Thx! – Stas

3

对不起,没有这样的Class对象,因为,正如你注意到的,擦除意味着不可能存在。你需要将其强制转换:

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

这会给你想要的界限,而是因为你执行的是未经检查的一般投可能会产生编译器警告。这是合理的:编译器要求您承认您将遗留泛型的编译时安全性。但在这种情况下,这种情况实际上不会在您的程序或将来产生运行时错误,所以没关系。

因为编译器知道Foo.class与Class>不兼容,所以必须首先将其转换为“raw”类型Class:在表达式中使用原始类型会禁用编译器的通用属性类型检查表达式,所以然后“不可能”的演员工作正常。

0

由于java.lang.Class中是不可变的,你可以在使用弱类型声明酒吧的构造函数:

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>它是安全的,在构造函数中丢的。