Java tamp foundation (59) - Generics

1. What is a generic

Generics are the new features Java1.5 appear, it is the most important characteristic. Generic nature of the parameter type, data type that is being operated is specified as a parameter. This parameter type may be used in the creation of classes, interfaces and methods, generic class, generic interfaces, generic methods are called. This parameter determines the type of the program is running.

We can be understood as a generic role in the class or interface the label. Depending on the type of the incoming label specified data type, otherwise it will go wrong, where the type must be a class type, not the basic data types. For example, we saved the State TCM medicine boxes, each box above are affixed with a label, if the above is posted Cordyceps sinensis, then it can only put Cordyceps sinensis, and while other drugs mixed together in very chaotic, it is prone to error.

Generics is one such reason, we first look at the generic easiest to use it:

The ArrayList <String> List = new new the ArrayList <> (); 
List.add ( "the Hello" );
 // only put string, if the compiler to put the digital error
 // List.add (666);

Note: After Java1.7 generics can be simplified, which is in front of the variable parameter types must be written, and the latter parameter type can be written, it can be omitted.

2. Why generics

For a simple example, this should be the Internet's most classic example:

    // Create a set of objects 
    the ArrayList List = new new the ArrayList (); 
    List.add ( "the Hello" ); 
    List.add ( "World" ); 
    List.add ( 111 ); 
    List.add ( 'A' );
     // iterate set content 
    for ( int I = 0; I <list.size (); I ++ ) { 
        String STR = (String) List.get (I); 
        System.out.println (STR); 
    }

There is no doubt the result of running the above program will be abnormal java.lang.ClassCastException: java.lang.Integer can not be cast to java.lang.String, this is no generic defects. Because above the ArrayList can store any type (ie Object type), we know that all types can be used to represent the Object type, and Object error prone in terms of the type of conversion.

Some might want to be replaced by the Object type String reception, then converted into data corresponding to the type, this is also possible, but in the event of a data type conversion when wrong or wrong, it also conversion will not appear abnormal. Even good luck all right, but this casts a lot of code, your colleagues or leadership saw the knife could be hacked you, is not conducive to post-maintenance code.

Visible Without generics is totally unacceptable, and we can draw some of the benefits brought by generics:

①, can effectively prevent the occurrence of abnormal type conversion.

②, can make the code more concise and to improve the readability, maintainability and stability of the code.

③, the collection may be enhanced for loop iterates, lead to better performance, since they are all of the same type.

④, can solve the type safety compiler warnings. Because all types of transformation without generics up as Object type, there is a type of security issues.

It generic three different ways, namely: a generic class, generic interfaces, generic method. We will then learn how to use them.

3, generic class

Generic class is defined in the generic class, it's relatively simple to use. Let's take the most common definition of a generic class:

// define a generic class, where T represents a generic identification 
public  class the Generic <T> { 
 
    Private T Key;
 
    public the Generic () { 
    } 
   
    public the Generic (T Key) {
         the this .key = Key; 
    } 
    // this is not pan type process, they are different 
    public T getKey () {
         return Key; 
    } 

    public  void setKey (T Key) {
         the this .key = Key; 
    } 
}

The generic class as the test code, we can just pass the desired type class instantiation, and T the generic class will be automatically converted into the corresponding type.

    public  static  void main (String [] args) {
         // there argument constructor initializes a String passed 
        the Generic <String> Generic = new new the Generic <> ( "Generic1 ..." ); 
        System.out.println (Generic. getKey ()); // Generic1 ...
         // constructor with no arguments is initialized, the type Integer passing 
        the Generic <Integer> = Generic1 new new the Generic <> (); 
        generic1.setKey ( 123456 );
         int Key = generic1.getKey ( ); 
        System.out.println (Key); // 123456 
    }

We then look at generics generic identifiers, above this generic class is represented by T in any type, there are many such generic identification, for example, K represents a bond, V represents the value, E is set, N represents the number of sub-type and the like.

In particular there are two generic classes of use, it is the inheritance passed in time whether specific parameters.

①, when subclasses of the generic class clear when the incoming generic argument:

// subclass explicitly passed in the generic parameter type 
class SubGeneric the extends the Generic <String> { 

} 
// test class 
class the Test {
     public  static  void main (String [] args) { 
        SubGeneric subGeneric = new new SubGeneric ();
         // call property is inherited from the parent class 
        subGeneric.setKey ( "SubGeneric ..." ); 
        String Key = subGeneric.getKey (); 
        System.out.println (Key); 
    } 
}

When can draw a subclass inherits the parent class with generics, clearly indicates the type of the parameter passed, then the child class at instantiation, do not need to specify generic, using a type of the parent class.

②, when the subclass inherits the generic class does not explicitly passed in the generic argument:

// the sub-generic class parameter type is not explicitly passed 
class SubGeneric <T> the extends the Generic <T> {
     Private T value; 

    public T the getValue () {
         return value; 
    } 

    public  void the setValue (T value) {
         the this .Value = value ; 
    } 
} 

class the Test {
     public  static  void main (String [] args) { 
        SubGeneric <Integer> = subGeneric new new SubGeneric <> ();
         // call the property is inherited from the parent class 
        subGeneric.setKey (123456 );
        int key = subGeneric.getKey();
        System.out.println(key);
        //调用子类自己的属性
        SubGeneric<String> subGeneric1=new SubGeneric<>();
        subGeneric1.setValue("SubGeneric...");
        String value = subGeneric1.getValue();
        System.out.println(value);
    }
}

When the subclass is not explicitly passed in the parameter type, then the type is instantiated when the subclass, the subclass is passed according to the determined type of the parent class. If the parent and child classes in a clear, another no clear or both explicit type is not the same, then they are automatically promoted to the type of Object type. as follows:

// a clear, an ambiguous 
class SubGeneric <T> the extends the Generic <String> {
     Private T value; 
}

4, generic interface

Defining and using generic interface and generic class is almost the same, but some difference in terminology in the statement above, so here is not to say anything. Direct look at an example:

// definition of a generic interface 
public  interface IGeneric <T> {
     public T Show (); 
} 

class the Test the implements IGeneric <String> { 
    
    @Override 
    public String Show () {
         return "Hello" ; 
    } 
}

Generic interface implementation class are clear arguments passed and generic class is the same, so do not say, can refer to the generic class.

5, generic method

Introduced in front of generic classes and generic interface, the use of both of them is relatively simple, then we look generic methods, generic method is slightly more complicated than both of them a little. In front of the generic class, we also see the method useful to generics, its format is as follows:

    // not a generic method described herein, they are different 
    public T getKey () {
         return Key; 
    }

But it is not a generic method. The generic method with the return value must be <generic identification> modified (including void), only declared <T> method is a generic method, where <T> indicates that the method will use the generic identity T in this case the method can only be used in a generic identification T. Alone with only a generic logo T said that it would be an error, could not understand what it is. Of course, we can also use other generic identifiers such as: K, V, E, N and the like.

Generic method statement format is as follows:

    // here generic identification of T and T generic classes nothing 
    public <T> T Show (T T) {
         return T; 
    }

Note: Generic generic and belongs to the class of generic method has nothing to do. We can illustrate:

public  class GenericMethod <T> { 

    // where the generic identity of T and T generic classes nothing 
    public <T> T Show (T T) {
         return T; 
    } 
} 

class the Test {
     public  static  void main (String [] args) {
         // instantiate a generic class, String type incoming 
        GenericMethod <String> = genericMethod new new GenericMethod <> ();
         // call the method, the incoming digital 
        Integer = genericMethod.show Show (123456 ); 
        the System. out.println (Show); // 123456
         // call the method, passing in character
        Character a = genericMethod.show('a');
        System.out.println(a);//a
    }
}

In the test class, you create an instance of the class, passed in the generic type is String, but when calling methods were introduced to digital type and character types.

Thus we conclude that: generic method is to specify generic specific types when calling methods, so generic method can be static; generic class and generic generic interface is specified in the specific instance of the class time type, so generic classes and generic interface methods can not be static.

6, generics reflected in the succession of (compatibility)

If a class inherits from another class, then the conversion between them will become as simple as Integer inherit Number:

    Number = 123 Number The ; 
    Integer Integer = 456 ; 
    Number = Integer; // can be assigned 

    Number The [] Numbers = null ; 
    Integer [] integers = null ; 
    Numbers = integers; // you can assign

The above is entirely possible to do so, but they are used in a generic is not so different story.

    List <Number The> List1 = null ; 
    List <Integer> List2 = null ;
     // compile error, incompatible type
     // List1 = List2;

This is because the Integer class inherits from Number, but not inherited from List <Number>, which two are both inherited from the root class Object List <Integer>. See image below may be better understood (picture quoted from https://blog.csdn.net/whdalive/article/details/81751200)

 

Used here to summarize this passage: Although class A is a superclass of B type, but G <A> and G <B> does not have any child parent relationship therebetween, both of which are side by side relationship, the relationship is only Object are inherited from the root class.

Then look at another scenario: with generic classes (interfaces) and another class (interfaces) have inheritance (implementation).

Example: in the collection, ArrayList <E> to achieve List <E>, List <E> extended Collection <E>. Thus ArrayList <String> is a List <String> subtype, List <String> is a Collection <String> subtype. So it does not change the type of parameters, will be in the relationship between the type of reserved sub-type.

    Collection<String> collection=null;
    List<String> list=null;
    ArrayList<String> arrayList=null;
    collection=list;
    list=arrayList;

In fact, here it is the common inheritance (realization), similar to Integer in Number inherit the same class. Picture the following:

Reference article: https://blog.csdn.net/whdalive/article/details/81751200

7, Tsuhaifu

? Why use a wildcard that it must be generic in some places is not perfect, so just use the wildcard Yeah, let's analyze:

In an above told us Integer is a subclass of Number, and both List <Integer> and List <Number> is a parallel relationship, there is no relationship between them, the only relationship that inherit from the Object the root class. So the question is, we use List <Number> as a form method when the Senate can pass List <Integer> as a parameter of type arguments can? In fact, this time the answer is already clear, is unacceptable. So this time we can use a wildcard.

In the case of no wild cards in our code to be written like this:

public class Generic {

    public static void main(String[] args) {
        List<Number> list1=new ArrayList<>();
        list1.add(1);
        list1.add(2);
        List<Integer> list2=new ArrayList<>();
        list2.add(3);
        list2.add(4);
        show(list1);
        //报错说不能应用Integer类型
        //show(list2);
    }

    public static void show(List<Number> list){
        System.out.println(list.toString());//[1, 2]
    }
}

If you want to support Integer type you need to add a new method:

    public static void show1(List<Integer> list){
        System.out.println(list.toString());//[1, 2]
    }

This will lead to a lot of redundant code that is not conducive to reading. So then we need generics wildcard in the following format:

    public static void show(List<?> list){
        System.out.println(list.toString());//[1, 2][3, 4]
    }

When we use a wildcard, you can easily solve the above problem. Using generics in Java ?  Number used to represent a wildcard? Wildcard indicates the current match any type, any Java class can match. But after using wildcards must pay attention to: the object of some methods can call any course, but there are ways you can not call. E.g:

    public  static  void Show (<?> List List) {
         // List.add (66); can not use the Add () 
        Object Remove list.remove = (0); // use Remove () 
        System.out.println (Remove ); 
        Object GET = List.get (0); // can use GET () 
        System.out.println (GET); 
        System.out.println (list.toString ()); 
    }

This is because only when called to know List <?> What is the specific type of wildcard Yes. So for the above list, if the call to add () method, then we do not know what type of add, it will be an error. And remove () and get () method is operated according to the index, they are digital type, it can be called.

7.1 Wildcard limit

 

7.2 emails Hythe lower limit

Guess you like

Origin www.cnblogs.com/tang-hao-/p/11347124.html