Java generics have always been a part of my interest, but since I'm talking about generics, I have to mention erasing. Java generics are implemented using erase, and when generics are used, the specific type information is "erased". For example,:list<string> and list<integer> are essentially the same type at run time, and are erased to the "native" type, which is List.
The generic type parameter will erase to its first boundary, such as list<t> will be erased to list, while the normal type variable is erased to object without specifying a boundary.
1 PackageCom.test.generic;2 3 Public classErased<t> {4 Private Final intSIZE = 100;5 Public Static voidf (Object Arg) {6 if(ARGinstanceofT) {}//Compile Error7T var =NewT ();//Compile Error8t[] Array =NewT[size];//Compile Error9t[] Array =NewOnject[size];//Compile ErrorTen } One}
View Code
Factory method
In the above code, the creation of a new T () operation cannot be implemented, partly because of the erasure, because the compiler cannot verify that the code T has a default (no parameter) constructor. The solution for Java is to pass a factory object and use it to create a new instance. The most convenient factory object is the class object, as shown in the following code:
1 PackageCom.test.generic;2 3 classClassasfactory<t> {4 T x;5 PublicClassasfactory (class<t>kind) {6 Try {7x =kind.newinstance ();8}Catch(Exception e) {9 Throw NewRuntimeException (e);Ten } One } A } - - classEmployee {} the - Public classInstantiategenerictype { - - Public Static voidMain (string[] args) { +classasfactory<employee> FE =NewClassasfactory<employee> (Employee.class); -System.out.println ("Classasfactory<employee> succeeded"); + A Try { atclassasfactory<integer> fi =NewClassasfactory<integer> (Integer.class); -}Catch(Exception e) { -System.out.println ("Classasfactory<employee> failed"); - } - } - in}
View Code
The operation results are as follows
As seen from the running results, it can be compiled, but it will fail because of classasfactory<integer> because the integer does not have any default constructors. Because this error is not captured at compile time. Sun recommends using an explicit factory and restricting the type to accept only the classes that implement the factory, as shown in the following code:
1 PackageCom.test.generic;2 3 InterfaceFactoryi<t> {4 T Create ();5 }6 7 classFoo2<t> {8 PrivateT x;9 Public<fextendsFactoryi<t>>Foo2 (F factory) {Tenx =factory.create (); One } A } - - classIntegerfactoryImplementsFactoryi<integer> { the PublicInteger Create () { - return NewInteger (0); - } - } + - classWidget { + Public Static classFactoryImplementsFactoryi<widget> { A @Override at PublicWidget Create () { - return Newwidgets (); - } - } - } - Public classFactoryconstraint { in Public Static voidMain (string[] args) { - NewFoo2<integer> (Newintegerfactory ()); to NewFoo2<widget> (Newwidget.factory ()); + } -}
View Code
Class<t> happens to be creating a built-in factory object, and you can get a compile-time check by creating a factory object as shown above.
Template method:
Another way is to use the template method design pattern, by implementing abstract class (template) abstract method to create objects, also can get compile time type check, the following is the code:
1 PackageCom.test.generic;2 3 Abstract classGenericwithcreate<t> {4 FinalT element;5 genericwithcreate () {6element =Create ();7 }8 AbstractT Create ();9 }Ten One classX {} A - classCreatorextendsGenericwithcreate<x> { - @Override the X Create () { - return NewX (); - } - voidf () { + System.out.println (Element.getclass (). Getsimplename ()); - } + } A Public classCreatorgeneric { at Public Static voidMain (string[] args) { -Creator C =NewCreator (); - c.f (); - } -}
View Code
Summarize:
In the process of using generics, any operation that needs to know the exact type of information at run time cannot work properly because of the erasure. By reflecting the use of a factory method or a template method, we can know whether the type of arguments passed when the object was created is correct in the compiler.
Java Design Patterns-factory methods & Template Methods