Java generic summary and Application
Introduction:
Before JDK1.5, When you store data into a set, you need to determine whether the type is valid. If you know that you are defining the String type, while you save an Integer data, compilation is successful, but it may cause type conversion exceptions during running.ClassCastExceptionThis is a serious security risk. After 1.5GenericAndGenericLater, this risk was exposed during the compilation period, so that developers can avoid this risk and avoid forced conversion. You can understand generics as a security mechanism of java. Of course, in addition to this function, generics make programs more universal and flexible, and at the same time bring about another object"Polymorphism". This is especially common in set operations.
Generic definition
GenericThe parameter type ". When it comes to parameters, the most familiar thing is that there are tangible parameters when defining a method, and real parameters are passed when you call this method. How can we understand parameterized types? As the name implies, the type is parameterized from the original specific type, similar to the variable parameter in the method. In this case, the type is also defined as a parameter (which can be called a type parameter ), then, specify the specific type (type real parameter) when using/calling ). When used in angle bracketsUnified Character,Generic limitationIt is a bit similar to the JavaScript "late binding" (that is, the compiler or interpreter does not need to explicitly know the object type before running)
Use 1 to define generic classes
In the definitionWhen a class with a type parameter is created, you can specify the names of one or more types of parameters in the <> after the class is followed. You can also set the value range of the type parameter, multiple types of parameters are separated by commas. After defining the type parameters, Almost any place of the class after the location is defined(Except static block, static attribute, and static method) use type parameters, Just like using a common type. Note:The type parameter defined by the parent class cannot be inherited by the quilt class..
public class GenericClass
{ .... }
From the above, we have a general understanding of generics, but it is still not clear about how to use generics and how to use generics, first, you can use an example that does not use generics and an example that uses generics to describe the following requirements: assume that you have a tool class that is used to operate other entity classes (internal details are ignored)
Class Payout {...} class Income {...} // class Utils {private Object obj; public void setObject (Object obj) {this. obj = obj;} public Object get () {return obj ;}}
To use the Utils class to operate the object class, we first create a new Utils, then use Payout initialization, call the getObject method to obtain the object, and then forcibly convert it to the Income type,
Public static void main (String args []) {Utils t = new Utils (); t. setObject (new Payout (); Income in = (Income) t. getObject (); // The forced conversion exception is obvious, but the compilation is successful because no generic type is used}
Although the syntax is correct in this way, compilation can pass smoothly, but it is very dangerous to run an exception during forced conversion, on the contrary, if we use generics, We can perfectly avoid this risk and change the tool class
// Define the work class with the generic type. The tool class type is UtilsGeneric.
Class UtilsGeneric
{Private T; public void setObject (t T) {this. t = t;} public void getObject () {return this. t;}/* generic usage. This exposes the problem of type conversion during compilation. Note that the generic type defined by generic classes is valid throughout the class. If it is used by methods, after generic objects specify the specific types of operations, all the operation types are fixed, however, each method needs to operate on the same type of data to a certain extent, reducing the flexibility of generics */public void static main (String [] args) {UtilsGeneric
St = new UtilsGeneric
(); St. setObject (new Payout (); // Income stu = st. getObject (); Compilation failure Payout stu = st. getObject ();}
After a generic class is used, it is clearly specified when defining the tool class. the type to be operated is Payout.
2. Define generic methods
When defining methods with type parametersVisible Range Modification(For example, public)<>, SpecifyOne or more type parametersAnd the value of the type parameter.Define the range, Multiple typesUsed between parameters, no.Separated. After defining the type parameter, you can use the type parameter anywhere in the method after defining the location
public
T GenericFunction(T t, S s){ ... }
Application of generic methods:
// Define the generic method class GenericMethod {// it does not matter even if both are written as T, because the two are not associated with public
Void show (T t) {System. out. println (t);} public
Void prin (T t) {System. out. println (t );}}
Use generic methods
public static void main(String[] args){ GenericMethod m=new GenericMethod(); m.show(xianshiyong zifuchuan ); m.show(new Integer(8)); d.prin(new Integer(9)); d.prin(caozuo zifuchuan);}
3 nested generic methods in generic classes
There are generic methods in generic classes:T indicates the type only when the object is created.If there is a static method,Static methods cannot be generic defined on the generic class.If the data type of the application operated by the static method is unknown, you can define the generic type on the method.
// Use the generic method and static generic method in the generic class GenericClassMethod
{// Common method public void show (T t) {System. out. println (t);} // generic method public
Void prin (E e) {System. out. println (e);} // compilation failed. The error "non-static class T cannot be referenced from Static Context" is reported because the static class exists before the object. /* Public static void method (T t) {System. out. println (t);} * // static generic method public static
Void method (W t) {System. out. println (t );}}
Use generic classes and generic methods
// Generic method public static void main () {GenericClassMethod
M = new GenericClassMethod
(); M. show (xianshiyong zifuchuan); // m. show (new Integer (8); error because the String type d has been specified. prin (caozuo zifuchuan); d. prin (new Integer (9); GenericClassMethod. method (static generic method );}
4. generic interface
There is no major difference between the syntax of generic interfaces and generic classes.
// Define the generic Interface IConnet
{Void show (T t) ;}// you can specify the class ConnectImp implements IConnet
{Public void show (String t ){...}} // implement the generic interface. When you do not determine the data type, you can still reference the generic Tclass ConnectImp2 implements IConnet
{Public void show (T t ){...}}
Use generic Interfaces
Public static void main (String args []) {ConnectImp imp = new ConnectImp (); imp. show (sddd); // only ConnectImp2 of String type can be input
Imp = new ConnectImp2
(); Imp. show (9); // The type of incoming data depends on the Data Type <>}
5 wildcard characters?
We can also understand generic parameters (that is, the type in angle brackets) as method parameters. When the object type is unknown, we can use a wildcard "?" Wildcard represents any type, which is equivalent to a placeholder. it is replaced by a specific type during execution. Let's look at an example. We want to add a general method that can traverse all types of ArrayList. We don't know how many types we need to print before implementation, however, the use of objects may cause ClassCastException. At this time, the advantages of wildcards are exposed,
// Print the ArrayList object public static void printAll (ArrayList
Al) {Iterator
It = al. iterator (); // because the ArrayList type is not fixed, the iterator type and ArrayList are still not fixed while (it. hasNext () {System. out. println (it. next (); // System. out. println (it. next (). length (); incorrect, because not all types have this method. Obviously, if? Integer replacement does not have the length method} // Of course, public static void printAll (ArrayList
Al) {Iterator
It = al. iterator (); while (it. hasNext () {T t = it. next (); // The biggest difference between the wildcard and the wildcard, because T represents a specific type, while the wildcard does not represent a specific type, so it cannot be operated. S. o. p (it. next ());}}
Use wildcards
public static void main(String [] args){ ArrayList
al=new ArrayList
(); al.add(sdd); al.add(dfd); ArrayList
al2=new ArrayList
(); al2.add(9); al2.add(8); printAll(al); printAll(al2);}
Because Wildcards are used, no matter whether the output is String or Integer ArrayList, we do not need to pay attention to them when implementing the General Traversal method. Is it a bit like a placeholder in SQL?
6 generic limitation-upper and lower limits
The generic limitation syntax is no different from that of generic and generic interfaces. Generic limitation only applies to generic parameters.Limits some scopes-upper and lower limits.
Upper Limit: the upper limit is limited. <? Extends E> receives subclasses of E and E. Lower limit: downward limit. <? Super E> receives the parent classes of E and E.
From the above we can see that the wildcard can be used to perfectly solve the problem. The general traversal is a simple set of types, but what we want to save is the object? What is the inheritance relationship between the objects to be traversed? Obviously, wildcards are acceptable, but not all types of data are what we want. If we want a data type that has a relationship, please refer to an example.
Save the Person and Student objects to the ArrayList and traverse them using common methods.
class Person{ private String name; Person(String name){ this.name=name; } public String getName(){ return name; }}class Student extends Person{ public Student(String name){ super(name); }}
Implementation without generic limitation
public static void prinColl(ArrayList
pl){ Iterator
it=pl.iterator(); while(it.hasNext()){ T t=it.next(); s.o.p(it.next().getName()); }}
Test Traversal
ArrayList
Pl = new ArrayList
(); Pl. add (new Person (df); pl. add (new Person (er); pl. add (new Person (am); prinColl (pl); // It can be successfully traversed. // when Student is saved again, the ArrayList error is returned when printAll is called.
Sl = new ArrayList
(); Sl. add (new Student (son); sl. add (new Student (son2); sl. add (new Student (son3); // prinColl (pl); // compilation fails. The cause of the error is actually the ArrayList
Al = new ArrayList
() This is not allowed, because the Person to be stored in the set is declared. If there is a Person class that inherits the Person class, it cannot be stored, because only Student is stored in the new system, this creates a hidden risk that is not safe. So the compilation fails. The solution is that the types on both sides must be consistent.
The advantage of generic limitations is no doubt. We don't need to change the calling code, but just need to slightly change the Traversal method.
// Specify the type to be able to receive child classes of the Person type or Person type, that is, upper limit, public static void prinColl (ArrayList <? Extends Person> pl) {Iterator <? Extends Person> it = pl. iterator (); while (it. hasNext () {T t = it. next (); s. o. p (it. next (). getName ());}}