意外的泛型行为

时间:2010-03-15 06:50:02

标签: java generics

我发现了奇怪的泛型行为。用两个词 - 我真正想要的是以最常见的方式使用ComplexObject1,而我真正错过的是为什么定义泛型类型(... extends BuisnessObject)丢失了。 我的博客中也讨论了讨论主题 http://pronicles.blogspot.com/2010/03/unexpected-generics-behaviour.html

public class Test {

  public interface EntityObject {}

  public interface SomeInterface {}

  public class BasicEntity implements EntityObject {}

  public interface BuisnessObject<E extends EntityObject> {
    E getEntity();
  }

  public interface ComplexObject1<V extends SomeInterface> extends BuisnessObject<BasicEntity> {}

  public interface ComplexObject2 extends BuisnessObject<BasicEntity> {}

  public void test(){
    ComplexObject1 complexObject1 = null;
    ComplexObject2 complexObject2 = null;

    EntityObject entityObject1 = complexObject1.getEntity();
    //BasicEntity entityObject1 = complexObject1.getEntity(); wtf incompatible types!!!!
    BasicEntity basicEntity = complexObject2.getEntity();
  }
}

2 个答案:

答案 0 :(得分:2)

您的问题是您使用的原始类型ComplexObject1。它很容易修复:只需使用ComplexObject1<?>,您的代码编译就可以了。

这种行为真的没什么意外。

来自tutorial

  

存在类型擦除,以便新代码可以继续与遗留代码接口。 出于任何其他原因使用原​​始类型被认为是糟糕的编程习惯,应尽可能避免使用。

来自JLS 4.8 Raw Types(强调他们的):

  

原始类型的使用仅允许作为遗留代码兼容性的让步。强烈建议不要在将通用性引入Java编程语言之后编写的代码中使用原始类型。 未来版本的Java编程语言可能会禁止使用原始类型。

另请参阅 Effective Java 2nd Edition ,第23项:不要在新代码中使用原始类型。

答案 1 :(得分:1)

基本上,如果一个类具有泛型参数,并且在没有这些参数的情况下声明它,则它是一个原始类型。原始类型会在其成员中丢失泛型参数。

请参阅What is the raw type?

  

什么是原始类型?

     

没有任何类型参数的泛型类型。

     

没有任何类型的泛型类型   参数,如Collection,是   叫原始类型

Can I use a raw type like any other type?

  

原始类型的方法或构造函数   有他们的签名   有类型擦除后。

这使得人们陷入困境。例如:

public interface MyClass<T> {
  T foo();
  List<String> bar();
}

MyClass m = ...
List<String> list = m.bar(); // warning!

它让人感到困惑,因为此方法的返回类型与泛型类型参数无关,但这就是Java的工作方式。