Introduction
JDK1.5 after the introduction of generics, the beginning of the initial contact is difficult to understand, after a slow study, some harvest, now summed up, can deepen their own understanding, can also help others.
Due to my limited level, there is inevitably a wrong place, also please correct me. Needless to say, the following officially began.
For a more intuitive description of generics, it is now assumed that a driver is driving the scene. We need 3 classes, Driver (driver), Ford, Buick (Buick).
First edition
The first version of the code is as follows:
public class Buick {public void run () { System.out.println ("Buick Run"); } public void AutoRun () { System.out.println ("Buick Auto-run"); } }
public class Ford {public void run () {System.out.println ("Ford run"); } public void Fly () {System.out.println ("Ford Fly"); }}
public class Driver { private Object car; public void Drive (Object car) { This.car = car; if (car instanceof Buick) { System.out.println ("I am driving a" + car); ((Buick) car). Run (); } else if (car instanceof Ford) { System.out.println ("I am driving a" + car); ((Ford) car). Run (); } } Public Object Getdrivingcar () { return car; } public static void Main (string[] args) { Driver driver1 = new Driver (); Driver1.drive (New Ford ()); Driver driver2 = new Driver (); Driver2.drive (New Buick ()); //... Perform other business logic /** Gets the driver 1 Ford car to execute the Fly method */( (Ford) Driver1.getdrivingcar ()). Fly (); /** get driver 2 to open the Buick car to execute AutoRun method * /((Buick) Driver2.getdrivingcar ()). AutoRun ();} }
A brief description of the next three classes. The Buick class and the Ford class all contain the Run method, the Buick class has the Autorun method, the Ford class has the Fly method.
The driver class has a drive method and a Getdrivingcar method and an internal property of car. The main static method is a demonstration example.
As shown in the previous demo example, when invoking the drive method of an driver instance, the actual parameter is converted up to an object, and when the Getdrivingcar method is called, it needs to be transformed down to the specific car class to invoke its particular method. So what's wrong with this approach?
The problem is obvious that the parameter type of the drive method is the same as the return value type of Getdrivingcar, but because of the need to support different car, the upward transformation to the object type (not defined as the specific Buick type or Ford type), In this way, when calling Getdrivingcar, the outside is returned with a generalized object, which loses the characteristics of the specific class and requires an external coercion type conversion. This display coercion is prone to classcastexception exceptions (which are thrown when the code is executed accidentally when the Driver2 is written driver1), and this programming error cannot be found during compilation, but is not discovered until run time. It is possible to create a hidden bug. And this way is not reasonable, the use of the driver class threshold is too high, the external code needs to be handled with great care to prevent errors, for example, before casting with instanceof to judge. So there's no better way?
Second Edition
The second version of the Code is as follows (only the driver class is modified):
public class Driver<t> { private T car; public void Drive (T car) { This.car = car; if (car instanceof Buick) { System.out.println ("I am driving a" + car); ((Buick) car). Run (); } else if (car instanceof Ford) { System.out.println ("I am driving a" + car); ((Ford) car). Run (); } } Public T Getdrivingcar () { return car; } public static void Main (string[] args) { driver<ford> driver1 = new driver<ford> (); Driver1.drive (New Ford ()); driver<buick> driver2 = new driver<buick> (); Driver2.drive (New Buick ()); //... Perform other business logic /** Gets the driver 1 to drive the Ford car to execute the Fly method */ Driver1.getdrivingcar (). Fly (); /** get driver 2 to open the Buick car to execute AutoRun method */ Driver2.getdrivingcar (). AutoRun (); }}
The <t> used in the driver class declaration, or generic T. You can interpret the T type as a type that represents any particular type. Also modify the drive method parameter type and the Getdrivingcar method return value type and private property car are all t types. So what is the benefit of doing so?
From the demonstration of the main method, you can see that when instantiating the driver class, you need to specify the specific T type (Buick in Ford and Driver2 in Driver1). After instantiation, the return type of the calling Getdrivingcar method is also the appropriate specific type, allowing you to invoke specific type-specific methods directly.
Comparing the first version of the driver class, the improved version of the driver class, only requires the user to specify a specific T type when the class is instantiated, no forced type conversion is required in subsequent operations, thus reducing the likelihood of errors and increasing the robustness of the code.
with generic T, it's easy to unify the types of drive method parameter types, Getdrivingcar method return value types, and private property car types, without sacrificing the need for additional code costs, unlike the first version of car declaration as object type. The class structure looks clear. For external users, the use of the threshold is also low, there will be no careless mistake type error (want to appear also impossible, if the error type is specified, the error will be prompted during compilation)
The above example demonstrates the most basic usage of generics. Generics make it easy to declare a uniform type between a class's member variable or a method parameter or a method return value without sacrificing the specificity of the type, which is generic in the class definition, but you need to specify a specific type when instantiating
Practice
Now you should have a basic understanding of generics. Let's take an example from an example project to further illustrate the problem.
The project generally needs to be paged class, the simplified version is as follows
/** * < simple pagination class > */public class SimplePage { /** the number of records displayed per page */ private int numperpage; /** Total Record Count */ private int totalcount; /** Current Page */ private int pagenum; //... Omit Other methods}
/** * < with content Page class > */public class Pageable<e> extends SimplePage { /** * Page contents * / Private List <E> list; /** * < set contents > * @param list * /public void setlist (list<e> list) { this.list = List ; } /** * < get content > * @return * /Public list<e> getList () { return List; }}
SimplePage: A simple paging class that contains the current page, each page showing the number of records, the total number of records, and other basic member properties.
pageable: Business Data Paging class, continues from the simple pagination class, with this page data information.
For example, in order to query user information in the face, fake user-class encapsulation of users information. Use the following code:
pageable<user> pageInfo = new pageable<user> (); //... Paging Gets the user information, and calls the setlist method to put the user information into the PageInfo instance /** elsewhere to get to userlist, for other business operations */ list<user> userlist = Pageinfo.getlist ();
It is very simple to use, today is the code here, not to be continued.
Code word is not easy, reproduced please indicate the source
Java Generics Learning and Practice (1)