Self-bounded types(自限定的类型)

You can't inherit directly from a generic parameter.However,you can inherit from a class that uses that generic parameter in its own definition.That is, you can say:(你不能直接继承一个泛性参数,但是,你可以继承一个类,这个这类在它的定义中使用泛性参数,也就是说,可以声明:) 
  1. class GenericType<T> {} 
  2. public class CuriouslyRecurringGeneric  
  3.     extends GenericType<CuriouslyRecurringGeneric>{ 
  4.  
 
This could be called curiously recurring generics(CRG) after Jim Coplien's Curiously Recurring Template Pattern in C++.The "curiously recurring" part refers to the fact that your class appears,rather curiously,in its own base class.(你的类又在你的基类中出现,说的是作为你的类的父类的泛性参数)
 
To understand what this means,try saying it aloud:"I'm creating a new class that inherits from a generic type that takes my class name as its parameter."What can the generic base type accomplish(完成) when given the derived class name?Well,generics in Java are about arguments and return types,so it can produce a base class that uses the derived type for its arguments and return types.It can also use the derived type for field types,even though those will be erased to Object.(这里面说的意思是在泛性基类中泛性参数T,在使用子类的时候都会被替换成子类,子类是父类的属性的类型,子类是父类方法的返回值的类型,记住是在子类对象中使用任何父类的方法)
  1. public class BasicHolder<T> { 
  2.     T element; 
  3.     void set(T arg){ element = arg; } 
  4.     T get(){ return element; } 
  5.     void f(){ 
  6.         System.out.println(element.getClass().getSimpleName()); 
  7.     } 
It's an ordinary generic type with methods that both accept and produce objects of the parameter type,along with a method that operates on the stored field(althought it only performs Object opreations on that field).
 
  1. class Subtype extends BasicHolder<Subtype> {} 
  2.  
  3. public class CRGWithBasicHolder{ 
  4.     public static void main(String[] args){ 
  5.         Subtype st1 = new Subtype(), st2 = new Subtype(); 
  6.         st1.set(st2); 
  7.         Subtype st3 = st1.get(); 
  8.         st1.f(); 
  9.     } 
  10.      
Notice something important here:The new class Subtype takes arguments and return values of Subtype,not just the base class BasicHolder.This is the essence of CRG:The base class substitutes the derived class for its parameters.(基类用子类替换基类的参数)This means that the generic base class becomes a kind of template for common functionality for all of its derived classes,but this functionality will use the derived type for all of its argumetns and return values.That is,the exact type instead of the base type will be used in the resulting class.So in Subtype,both the argument to set() and the return type of get() are exactly Subtypes.
 
 
Selft-bounding
The BasicHolder can use any type as its generic parameter,as seen here:
  1. class Other{} 
  2. class BasicOther extends BasicHolder<Other>{} 
  3. public class Unconstrained { 
  4.     public static void main(String[] args){ 
  5.         BasicOther b = new BasicOther(), 
  6.                    b2 = new BasicOther(); 
  7.         b.set(new Other()); 
  8.         Other other = b.get(); 
  9.         b.f(); 
  10.     } 
Self-bounding takes the extra step of forcing the generic to be used as its own bound argument.(自限定将采取额外的步骤,强制泛性当作其自己的边界参数来使用)Look at how the resulting class can and can't be used:
  1. class SelfBounded<T extends SelfBounded<T>> { 
  2.     T element; 
  3.     SelfBounded<T> set(T arg){ 
  4.         element = arg; 
  5.         return this
  6.     } 
  7.     T get(){ return element; } 
  8.  
  9. class A extends SelfBounded<A>{} 
  10. class B extends SelfBounded<A>{} //Also OK 
  11.  
  12. class C extends SelfBounded<C>{ 
  13.     C setAndGet(C arg){ set(arg); return get();} 
  14.  
  15. class D{} 
  16.  
  17. //Can't do this: 
  18. /* 
  19. - Bound mismatch: The type D is not a valid substitute for  
  20.  the bounded parameter <T extends SelfBounded<T>> of the  
  21.  type SelfBounded<T> 
  22. - Occurrence of 'D' 
  23. */ 
  24. //class E extends SelfBounded<D>{} 
  25. //Compile error:Type parameter D is not within its bound 
  26.  
  27. //Alas,you can do this,so you can't force the idiom: 
  28. class F extends SelfBounded{} 
  29.  
  30. public class SelfBounding{ 
  31.     public static void main(String[] args){ 
  32.         A a = new A(); 
  33.         a.set(new A()); 
  34.         a = a.set(new A()).get(); 
  35.         a = a.get(); 
  36.         C c = new C(); 
  37.         c = c.setAndGet(new C()); 
  38.     } 
  39.      
 What self-bounding does is require the use of the class in an inheritance relationship like this: 
class A extends SelfBounded<A>{}
 
This forces you to pass the class That you are defining as a parameter to the base class.
What's the added value in self-bounding the parameter?The type parameter must be the same as the class being defined.As you can see in the definition of class B,you can also derive from a SelfBound that uses a parameter of another SelfBounded,although the predominant(主要的) use seems to be the one that you see for class A.The attempt to define E shows that you cannot use a type parameter that is nto a SelfBounded.
 
Unfortunately,F compiles without warnings,so the self-bounding idion is not enforceable.If it's really important,it may require an external tool to ensure that raw types are not being used in place of parameterized types.
 
Notice that you can remove the constraint and all the classes will still compile,but E will also compile:
  1. public class NotSelfBounded<T> { 
  2.     T element; 
  3.     NotSelfBounded<T> set(T arg){ 
  4.         element = arg; 
  5.         return this
  6.     } 
  7.      
  8.     T get(){ return element;} 
  9.  
  10. class A2 extends NotSelfBounded<A2>{} 
  11. class B2 extends NotSelfBounded<A2>{} 
  12.  
  13. class C2 extends NotSelfBounded<C2>{ 
  14.     C2 setAndGet(C2 arg){ set(arg); return get();} 
  15.  
  16. class D2{} 
  17. //Now this is Ok: 
  18. class E2 extends NotSelfBounded<D2>{} 
So clearly,the self-bounding constraint serves only to force the inheritance relationship.If you use self-bounding,you know that type parameter used by the class will be the same basic type(相同的基类) as the class that's using that parameter.It forces anyone using that class to follow that form.
It's also possible to use self-bounding for generic methods:
  1. public class SeleBoundingMethods { 
  2.     static <T extends SelfBounded<T>> T f(T arg){ 
  3.         return arg.set(arg).get(); 
  4.     } 
  5.     public static void main(String[] args){ 
  6.         A a = f(new A()); 
  7.     } 
This prevents the method from being applied to anything but a self-bounded argument of the form shown.
 
在这里说一点我自己的理解:
不管是这种形式:
  1. class GenericType<T> {} 
  2. public class CuriouslyRecurringGeneric  
  3.     extends GenericType<CuriouslyRecurringGeneric>{ 
  4.  
 
还是这种形式:
  1. class SelfBounded<T extends SelfBounded<T>> { 
  2.     T element; 
  3.     SelfBounded<T> set(T arg){ 
  4.         element = arg; 
  5.         return this
  6.     } 
  7.     T get(){ return element; } 
  8.  
  9. class A extends SelfBounded<A>{} 
  10. class B extends SelfBounded<A>{} //Also OK 
都会用子类或者是从父类继承出来的子类来作为父类的实际参数,只不过第二种会直接强迫你要使用从父类继承出来的子类来作为参数,可以是本身或者是其他子类
11