开发者

Unexpected generics behaviour

开发者 https://www.devze.com 2022-12-23 02:22 出处:网络
I found strange generics behaviour. In two words - thing I realy want is to use ComplexObject1 in most general way, and the thing I realy missed is why define开发者_运维知识库d generic type(... extend

I found strange generics behaviour. In two words - thing I realy want is to use ComplexObject1 in most general way, and the thing I realy missed is why define开发者_运维知识库d generic type(... extends BuisnessObject) is lost. The discuss thread is also awailable in my blog 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();
  }
}


Your problem is that you're using a raw type of ComplexObject1. It's easy to fix: just use ComplexObject1<?> instead, and your code compiles fine.

There's really nothing unexpected about this behavior at all.

From the tutorial:

Type erasure exists so that new code may continue to interface with legacy code. Using a raw type for any other reason is considered bad programming practice and should be avoided whenever possible.

From JLS 4.8 Raw Types (emphasis theirs):

The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of genericity into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.

See also Effective Java 2nd Edition, Item 23: Don't use raw type in new code.


Basically if a class has generic arguments and you declare it without those parameters, it is a raw type. Raw types lose generic arguments in their members.

See What is the raw type?

What is the raw type?

The generic type without any type arguments.

The generic type without any type arguments, like Collection, is called raw type.

and Can I use a raw type like any other type?

Methods or constructors of a raw type have the signature that they would have after type erasure.

This confuses people in corner cases. For example:

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

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

It confuses people because the return type of this method has nothing to do with the generic type argument but that's how Java works.

0

精彩评论

暂无评论...
验证码 换一张
取 消