Collections.max函数申明中的泛型

来源:互联网 发布:推筒子软件 编辑:程序博客网 时间:2024/05/21 07:13
How do I avoid breaking binary compatibility when I generify an existing type or method? 
 Sometimes a dummy bound does the trick.Occasionally, one must pay attention to the fact that a generification might change the signature of some methods in the byte code.  Changing the signature will break existing code that cannot be recompiled and relies on the binary compatibility of the old and new version of the .class file. 

Example (before generification, taken from package java.util ): 

class Collections { 
  public static Object max( Collection coll) {...}  
  ... 
}
The max method finds the largest element in a collection and obviously the declared return type of the method should match the element type of the collection passed to the method.  A conceivable generification could look like this.

Example (after a naive generification): 

class Collections { 
  public static <T extends Comparable<? super T>> 
  max(Collection <? extends T> coll)  {...}  
  ... 
}
While this generification preserves the semantics of the method, it changes the signature of the max method.  It is now a method with return type Comparable , instead of Object . 

Example (after type erasure): 

class Collections { 
  public static Comparable max( Collection coll)  {...}  
  ... 
}
This will break existing code that relies on the binary compatibility of the .class files.  In order to preserve the signature and thus the binary compatibility, an otherwise superfluous bound can be used. 

Example (after binary compatible generification, as available in package java.util ): 

class Collections { 
  public stati c <T extends Object & Comparable<? super T>> 
  T max(Collection <? extends T> coll)  {...} 
  ... 
}
The leftmost bound of the type parameter is now type Object instead of type Comparable , so that the type parameter T is replaced by Object during type erasure. 

Example (after type erasure): 

class Collections { 
  public static Object max( Collection coll)  {...}  
  ... 
}


Afterthought: 

Perhaps you wonder why the hack decribed in this FAQ entry is needed.  Indeed, had the Collections.max method been defined as returning a Comparable in the first place, no further measures, such as adding Object as a type parameter bound, had been required to preserve binary compatibility. Basically, the declared return type Object is a mistake in the design of this method. 

If you carefully study the specification of the Collections.max  method's functionality then you realize that all elements of the collection are required to implement the Comparable interface.  Consequently, the returned object is Comparable , too.  There is no reason why the method should return an Object reference. 

The only explanation one can think of is that in pre-generic Java there was no way of ensuring by compile-time type checks that the Collection contains only Comparable objects.  However, this was ensured via runtime type checks, namely an explicit downcast in the implementation of the method.  Hence this is not really an excuse for the bug. 

Note, that the runtime time type check in the pre-generic version of the Collections.max method still exists in the generic version.  The former explicit cast is now an implicit one generated by the compiler.  In the generic version, this cast can never fail (unless there are unchecked warnings), because the type parameter bound Comparable ensures at compile-time that the elements in the Collection are Comparable .

0 0
原创粉丝点击