I must admit that I am not a Java programmer. Daily development mainly involves C ++ and Delphi. I use Java to develop Android applications completely. Today, I am looking at Java's generics. Some aspects are very strange. Let's look at the following code:
Class Shape {
Public void Draw (){
System. out. println ("Draw Shape ");
}
}
Class Rect extends Shape {
@ Override
Public void Draw (){
System. out. println ("Draw Rect ");
}
}
Class Line extends Shape {
@ Override
Public void Draw (){
System. out. println ("Draw Line ");
}
}
Class Drawer <T> {
Public void DrawShape (T shape ){
Shape. Draw ();
}
}
Drawer is a generic class. The DrawShape method is used to draw a graph. From the experience of using the C ++ template, this is absolutely correct, but Java has a compilation error: shape. draw calls are not allowed.
I modified the code again:
Class Drawer <T> {
Public void DrawShape (T shape ){
Shape. toString ();
}
}
So the compilation is passed. It seems that Java has interpreted T as an Object. Is there any way to interpret it as a Shape? after reading the document, I know to write it like this:
Class Drawer <T extends Shape> {
Public void DrawShape (T shape ){
Shape. Draw ();
}
}
In the original type, you can also specify the inheritance. If so, what is the difference between the inheritance and non-generic code:
Class Drawer {
Public void DrawShape (Shape shape ){
Shape. Draw ();
}
}
It seems that Java's generics are quite different from C ++'s templates. Java's generics are mostly used for containers, and in my opinion, its biggest function is to save the operation of type conversion and check whether the type is correct during compilation. The traditional container class may need to be written as follows:
List intList = new ArrayList ();
IntList. add (new Integer (10 ));
Integer I = (Integer) intList. get (0 );
With the generic type, you can write it like this:
List <Integer> intList = new ArrayList <Integer> ();
IntList. add (new Integer (10 ));
Integer I = intList. get (0 );
I also noticed that generic parameters cannot be basic types, but only objects. This is a further widening gap with the C ++ template. I feel that Java generics are not very useful, but complicated. For example, if wildcard characters are used, let's look at the following code:
Private static void PrintList (List <Object> list ){
For (Object o: list ){
System. out. println (o. toString ());
}
}
Public static void DoTest (){
List <Rect> intList = new ArrayList <Rect> ();
IntList. add (new Rect ());
IntList. add (new Rect ());
IntList. add (new Rect ());
PrintList (intList );
}
PrintList cannot be compiled because List <Rect> is incompatible with List <Object>:
Private static void PrintList (List <?> List ){
For (Object o: list ){
System. out. println (o. toString ());
}
}
List <?> It means that the element type of the List is unknown, but it is always normal to become an Object, so it can be compiled. What should I do if I want it to be a Shape, how to add Extends with wildcards:
Class Shape {
Public String getName (){
Return "Shape ";
}
}
Class Rect extends Shape {
@ Override
Public String getName (){
Return "Rect ";
}
}
Public class TestGenerics {
Private static void PrintList (List <? Extends Shape> list ){
For (Shape s: list ){
System. out. println (s. getName ());
}
}
Public static void DoTest (){
List <Rect> intList = new ArrayList <Rect> ();
IntList. add (new Rect ());
IntList. add (new Rect ());
IntList. add (new Rect ());
PrintList (intList );
}
}
Look at List <? Extends Shape> list: I am almost dizzy. It means that the items in List must be Shape or inherited from Shape, after a circle, the problem can be solved by returning to the use of polymorphism.
However, this usage imposes some restrictions, that is, List <? The list in extends Shape> list cannot add or delete elements, for example:
Private static void PrintList (List <? Extends Shape> list ){
For (Shape s: list ){
System. out. println (s. getName ());
}
List. add (new Line ());
}
The list. add (new Line () statement cannot be compiled because the collection class with wildcards cannot determine the type of Its element.
I personally think Java should not be generic.