Java generics in-depth explanation

Source: Internet
Author: User
Tags java se

Java generics are a new feature of Java SE 1.5, where the essence of generics is a parameterized type, meaning that the data type being manipulated is specified as a parameter. This type of parameter can be used in the creation of classes, interfaces, and methods, called generic classes, generic interfaces, and generic methods, respectively. A generic type parameter can only be a class type (including a custom class) and cannot be a simple type. The benefits of introducing generics into the Java language are simple and secure.

Basic Introduction
In the case of Java SE 1.5, without generics, the "arbitrariness" of arguments is implemented by reference to type object, and the disadvantage of "arbitrariness" is to make explicit coercion of type conversions, which require the developer to be able to predict the actual parameter type. In the case of coercion of type conversion errors, the compiler may not prompt for an error and an exception occurs at run time, which is a security risk.

The benefit of generics is that it checks for type safety at compile time, and all casts are automatic and implicit, increasing the rate of reuse of the code.

Rule Limits
1. A generic type parameter can only be a class type (including a custom class) and cannot be a simple type.

2, the same generic can correspond to multiple versions (because the parameter type is indeterminate), different versions of the generic class instances are incompatible.

3, generic type parameters can have more than one.

4. The generic parameter type can use the extends statement, for example. It is customary to call it "bounded type".

5. The parameter type of a generic type can also be a wildcard type.

Generics and interfaces, methods and so on, a lot of content, it takes some effort to understand mastery and proficiency in the application. Here are the two examples I used to know about generics (based on impressions), to achieve the same functionality, one that uses generics, one that is not used, and that, by contrast, can quickly learn generics, learning that this basically learns the content of generics 70%.

Example one: Use of generics

Class Gen<t> {PrivateT ob;//define generic member variables Public Gen(T ob) { This. OB = OB;} PublicTGetob() {returnOB;} Public void Setob(T ob) { This. OB = OB;} Public void ShowType() {System. out. println ("The actual type of T is:"+ Ob.getclass (). GetName ());}} Public classGendemo { Public Static void Main(string[] args) {//Define an integer version of generic class GenGen<integer> intob=NewGen<integer> ( the); Intob.showtype ();intI= Intob.getob (); System. out. println ("Value="+ i); System. out. println ("----------------------------------");//Define a string version of generic class GenGen<string> strob=NewGen<string> ("Hello gen!"); Strob.showtype (); String S=strob.getob (); System. out. println ("Value="+ s);}}

Example two: no generics used

Class Gen2 {PrivateObject ob;//Define a common type member Public Gen2(Object ob) { This. OB = OB;} PublicObjectGetob() {returnOB;} Public void Setob(Object ob) { This. OB = OB;} Public void Showtyep() {System. out. println ("The actual type of T is:"+ Ob.getclass (). GetName ());}} Public classGenDemo2 { Public Static void Main(string[] args) {//Define an integer version of class Gen2Gen2 Intob =NewGen2 (NewInteger ( the); Intob.showtyep ();inti = (Integer) Intob.getob (); System. out. println ("Value="+ i); System. out. println ("---------------------------------");//Define a string version of Class Gen2Gen2 Strob =NewGen2 ("Hello gen!"); Strob.showtyep (); string s = (string) Strob.getob (); System. out. println ("Value="+ s);}}

Operation Result:

Two examples run the demo result is the same, the console output results are as follows:

The actual type of T is:

Java.lang.Integer

Value= 88

The actual type of T is: java.lang.String

Value= Hello gen!

Process finished with exit code 0

See this, the basic generic application and code reading will not be a problem.

drill-down generics
Original code

There are two classes below, to construct an object of two classes, and to print out the respective member X.

 Public classStringfoo {PrivateString x; Public Stringfoo(String x) { This. x = x;} PublicStringGetX() {returnx;} Public void SetX(String x) { This. x = x;}} Public classDoublefoo {PrivateDouble x; Public Doublefoo(Double x) { This. x = x;} PublicDoubleGetX() {returnx;} Public void SetX(Double x) { This. x = x;}}

Refactoring

Because the logic of the members and methods is the same in the class above, the types are different, so refactoring is considered. object is the parent class of all classes, so consider using object as a member type, so you can implement generic, which is actually "object generic", which is called temporarily.

publicclass ObjectFoo {private Object x;publicObjectFoo(Object x) {this.x = x;}publicgetX() {return x;}publicvoidsetX(Object x) {this.x = x;}}

Write the demo method as follows:

 Public classObjectfoodemo { Public Static void Main(String args[]) {Objectfoo Strfoo =NewObjectfoo (NewStringfoo ("Hello generics!")); Objectfoo Doufoo =NewObjectfoo (NewDoublefoo (NewDouble (" the")); Objectfoo Objfoo =NewObjectfoo (NewObject ()); System. out. println ("strfoo.getx="+ (Stringfoo) strfoo.getx ()); System. out. println ("doufoo.getx="+ (Doublefoo) doufoo.getx ()); System. out. println ("objfoo.getx="+objfoo.getx ());}}

The results of the operation are as follows:

[Email protected]

[Email protected]

[Email protected]

Explanation: Prior to Java 5, in order for a class to be generic, the parameter type, return type is often set to the object type, and when these return types are obtained to use, it must be "coerced" to the original type or interface before the method on the object can be called.

Generics to implement

Forcing type conversion is cumbersome, and I have to know in advance what the specific type of object is, in order to make the correct conversion. Otherwise, if the conversion is of the wrong type, such as "Hello generics!" The string is cast to double, then the compile time will not error, but the run time is dead. There is no way to cast--there, instead of using the JAVA5 generic to achieve.

 Public classgenericsfoo<t> {PrivateT x; Public Genericsfoo(T x) { This. x = x;} PublicTGetX() {returnx;} Public void SetX(T x) { This. x = x;}} Public classGenericsfoodemo { Public Static void Main(String args[]) {genericsfoo<string> strfoo=NewGenericsfoo<string> ("Hello generics!"); Genericsfoo<double> doufoo=NewGenericsfoo<double> (NewDouble (" the")); Genericsfoo<object> objfoo=NewGenericsfoo<object> (NewObject ()); System. out. println ("strfoo.getx="+strfoo.getx ()); System. out. println ("doufoo.getx="+doufoo.getx ()); System. out. println ("objfoo.getx="+objfoo.getx ());}}

Operation Result:

Strfoo.getx=hello generics!

doufoo.getx=33.0

[Email protected]

It's exactly the same as using the "object generic" approach, but the demo is much simpler and there's no coercion type conversion information.

The syntax for the generic class above is explained below:

Use to declare a type holder name, and then you can declare a member, a parameter, and a return value type as a type representation.

Of course T is just a name, and the name can be defined by itself.

Class Genericsfoo declares a generic class that does not have any limitations, actually equivalent to the object type, which is actually equivalent to class Genericsfoo.

When you declare and construct an instance of a class that uses generics, as compared to the object generic class, you can use "< actual type >" To specify the true type of the generic type holder. Classes such as

Genericsfoo doufoo=new Genericsfoo (New Double ("33"));

Of course, it is also possible to construct an object without using angle brackets to specify the true type of the generic type, but when you use the object, you need to cast it. For example: Genericsfoo doufoo=new genericsfoo (New Double ("33"));

In fact, when you construct an object without specifying type information, the object type is used by default, which is why you can make a stronger conversion.

Advanced Applications
Restricting generics

In the example above, because there is no limit to the range of class Genericsfoo type holder T, the qualified type here is actually the equivalent of object, which is the same as the "object generic" substance. Limitations such as we want to limit T to the set interface type.

Class Genericsfoo, such that generic t in a class can only be an implementation class of the collection interface, and an error occurs when an incoming non-collection interface is compiled.

Note: The qualification here is extends with the keyword, which can be either a class or an interface. But the extends here is not the meaning of the inheritance, it should be understood that the T type is the type that implements the collection interface, or T is the type that inherits the XX class.

The following continues to improve on the example above, as long as I implement the type of the collection interface:

publicclass CollectionGenFoo<T extends Collection> {private T x;public CollectionGenFoo(T x) {this.x = x;}public T getX() {return x;}publicvoid setX(T x) {this.x = x;}}

This can be written when instantiated:

public   Class  Collectiongenfoodemo {public  static  void  main  (String args[]) { collectiongenfoo<arraylist> Listfoo = null ; listfoo = new  Collectiongenfoo<arraylist> (new  ArrayList ()); //error, do not let this dry.  //originally written by the author of this place is wrong, you need to change Listfoo listFoo1  // Collectiongenfoo<collection> listFoo1 = null;  //listfoo1=new collectiongenfoo<arraylist> (New ArrayList ());  System. out . println ( "instantiated successfully!" );}}  

The current reading of this notation is that it can be compiled and run successfully. But the two lines commented out plus the error, because when defining the type, it is limited to construct such an instance of the time t is a certain type, this type implements the collection interface, but the implementation of the collection interface is a lot of classes, If you want to write specific subclass types for each type, it's too troublesome, I might as well use object general. Don't worry, generics have a better solution for this situation, which is "wildcard generics."

Multi-Interface Restrictions

Although Java generics simply use extends to represent the original concept of extends and implements, but still adhere to the application of the system, Java can only inherit one class, but can implement multiple interfaces, so you need to use a certain type of extends qualification, And there are many types of time, there can only be one is a class, and the class is written in the first bit, the interface is listed behind,

<T extends SomeClass & interface1 & interface2 & interface3>

The example here shows only the type qualification of a generic method, with exactly the same rules for the restriction of type parameters in a generic class, just the header of the class declaration,

publicclassDemo<TextendsComparable&Serializable>{//T类型就可以用Comparable声明的方法和Seriablizable所拥有的特性了}

Wild-Wildcard generics

In order to solve the disadvantage that the type is limited to dead dynamically based on the instance, the introduction of the "wildcard generic", for the above example, uses a wildcard generic format of "? "Represents an unknown type, this type is implemented collection interface.

public   Class  Collectiongenfoodemo {public  static  void  main  (String args[]) { collectiongenfoo<arraylist> Listfoo = null ; listfoo = new  Collectiongenfoo<arraylist> (new  ArrayList ()); //now it's not going to go wrong  //originally written by the author of this place is wrong, you need to change Listfoo listFoo1  collectiongenfoo<? Extends collection> listFoo1 = null ; Listfoo1=new  collectiongenfoo<arraylist> (new  ArrayList ()); System. out . println ( "instantiated successfully!" );}}  

Attention:

1. If you specify only, without extends, the default is to allow object and any Java classes below it. That is, any class.

2, wildcard generics can not only limit downward, for example, you can also limit upward, for example, a representation type can only accept double and its upper parent class type, such as number, an instance of type object.

3. Generic class definitions can have multiple generic parameters, separated by commas, and can also define generic interfaces, generic methods. These are similar to the usage rules for generics in generic classes.

Generic Methods
Whether you have a generic method is not related to whether the class it resides in is generic. To define a generic method, simply place the generic parameter list before the return value. Such as:

publicclass ExampleA {publicvoidf(T x) {System.out.println(x.getClass().getName());}publicstaticvoidmainnew ExampleA();ea.f(" ");ea.f(10);ea.f(‘a‘);ea.f(ea);}}

Output Result:

Java.lang.String

Java.lang.Integer

Java.lang.Character

ExampleA

When you use a generic method, you do not have to indicate the type of the parameter, and the compiler finds the specific type itself. A generic method is called just like a normal method, except that it is defined differently.

It is important to note that a static method cannot access the type parameters of a generic class, so if you want the static method to use generic capabilities, you must make it a generic method.

Java generics in-depth explanation

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.