Home>

we know,Define before using variables,When you define a variable, you must specify its data type.What kind of data is assigned to what kind of value.

Suppose we now define a class to represent coordinates,The data types of the coordinates are required to be integers, decimals, and strings.E.g:

x=10, y=10
x=12.88, y=129.65
x="Tokyo 180 degrees", y="210 degrees north latitude"

For different data types,In addition to method overloading,You can also use autoboxing and upward transformation.we know,Basic data types can be automatically boxed,Is converted into the corresponding packaging class;object is the ancestor of all classes,Instances of any class can be cast up to the object type, for example:

int->integer->object

double->double->object

string->object

In this way, only one method needs to be defined,You can receive all types of data.Look at the following code:

public class demo {
  public static void main (string [] args) {
    point p=new point ();
    p.setx (10);//int->integer->object
    p.sety (20);
    int x=(integer) p.getx ();//must be transformed downward
    int y=(integer) p.gety ();
    system.out.println ("this point is:" + x + "," + y);
    p.setx (25.4);//double->integer->object
    p.sety ("Tokyo 180 degrees");
    double m=(double) p.getx ();//must be transformed downward
    double n=(double) p.gety ();//throw an exception during runtime
    system.out.println ("this point is:" + m + "," + n);
  }
}
class point {
  object x=0;
  object y=0;
  public object getx () {
    return x;
  }
  public void setx (object x) {
    this.x=x;
  }
  public object gety () {
    return y;
  }
  public void sety (object y) {
    this.y=y;
  }
}

In the above code,There will be no problems when generating the coordinates,But when taking out the coordinates,To transform downwards,In the article Type Conversion of Java Polymorphic Objects, we talked aboutThere is a risk of downward transformation,And it is not easy to find during compilation,Exceptions are only thrown during runtime,So try to avoid downcasting.Run the above code,Line 12 throws a java.lang.classcastexception exception.

So is there a better way,Can you avoid overloading (with duplicate code) and minimize risk?

Yes, you can use a java class, which can accept any type of data.The so-called "generic type" is "broad data type", any data type.

Change the above code,Using generic classes:

public class demo {
  public static void main (string [] args) {
    //instantiate a generic class
    point<integer, integer>p1=new point<integer, integer>();
    p1.setx (10);
    p1.sety (20);
    int x=p1.getx ();
    int y=p1.gety ();
    system.out.println ("this point is:" + x + "," + y);
    point<double, string>p2=new point<double, string>();
    p2.setx (25.4);
    p2.sety ("Tokyo 180 degrees");
    double m=p2.getx ();
    string n=p2.gety ();
    system.out.println ("this point is:" + m + "," + n);
  }
}
//define generic class
class point<t1, t2>{
  t1 x;
  t2 y;
  public t1 getx () {
    return x;
  }
  public void setx (t1 x) {
    this.x=x;
  }
  public t2 gety () {
    return y;
  }
  public void sety (t2 y) {
    this.y=y;
  }
}

operation result:

this point is:10, 20
this point is:25.4, 180 degrees in Tokyo

Compared with the definition of ordinary classes,The above code adds 〈t1, t2〉 after the class name, t1, t2 are custom identifiers,Is also a parameter,The type used to pass the data,Not the value of the data,We call it a type parameter.In generics,Not only the value of the data can be passed through the parameters,The type of data can also be passed as a parameter.t1, t2 are just placeholders for data types,The runtime is replaced with a real data type.

Pass-by-value parameters (the parameters we usually call) are surrounded by parenthesesSuch as (int x, double y), type parameters (generic parameters) are enclosed by angle brackets,Multiple parameters are separated by commas,Such as<t>or<t, e> ;.

Type parameters need to be given after the class name.Once the type parameter is given,You can use it in the class.The type parameter must be a legal identifier,It ’s customary to use a single capital letter,usually,k for keys, v for values, e for exceptions or errors,t represents a data type in a general sense.

Generic classes must indicate the specific type when instantiated.That is, passing values ​​to type parameters,The format is:

 classname variable<datatype1, datatype2>= new classname<datatype1, datatype2>();

You can also omit the data type to the right of the equal sign,But it produces a warning,which is:

 classname variable<datatype1, datatype2>= new classname ();

Because the data type is specified when using a generic class,Assigning values ​​to other types will throw an exception,Neither need downcast,There are no potential risks,It's more practical than the autoboxing and upcasting that we introduced at the beginning of this article.

note:

Generics are a new feature of java 1.5.It is based on the C++ template,The essence is the application of parameterized types.

Type parameters can only be used to represent reference types,Cannot be used to represent primitive types,Such as int, double, char, etc. But passing basic types will not report an error,Because they are automatically boxed into the corresponding packaging class.

Generic method

In addition to defining generic classes,You can also define generic methods,For example, define a generic method that prints coordinates:

public class demo {
  public static void main (string [] args) {
    //instantiate a generic class
    point<integer, integer>p1=new point<integer, integer>();
    p1.setx (10);
    p1.sety (20);
    p1.printpoint (p1.getx (), p1.gety ());
    point<double, string>p2=new point<double, string>();
    p2.setx (25.4);
    p2.sety ("Tokyo 180 degrees");
    p2.printpoint (p2.getx (), p2.gety ());
  }
}
//define generic class
class point<t1, t2>{
  t1 x;
  t2 y;
  public t1 getx () {
    return x;
  }
  public void setx (t1 x) {
    this.x=x;
  }
  public t2 gety () {
    return y;
  }
  public void sety (t2 y) {
    this.y=y;
  }
  //define a generic method
  public<t1, t2>void printpoint (t1 x, t2 y) {
    t1 m=x;
    t2 n=y;
    system.out.println ("this point is:" + m + "," + n);
  }
}

operation result:

this point is:10, 20
this point is:25.4, 180 degrees in Tokyo

The above code defines a generic method printpoint (), which has ordinary parameters,There are also type parameters,The type parameter needs to be placed after the modifier and before the return value type.Once the type parameters are defined,You can use it in parameter lists, method bodies, and return value types.

Unlike using generic classes,It is not necessary to specify the parameter type when using a generic method,The compiler will automatically find the specific type based on the parameters passed.In addition to different definitions of generic methods,The call is just like a normal method.

Note:Generic methods are not necessarily related to generic classes.Generic methods have their own type parameters,Generic methods can also be defined in ordinary classes.The type parameters t1, t2 in the generic method printpoint () are not necessarily related to t1, t2 in the generic class point,You can also use other identifiers instead:

public static<v1, v2>void printpoint (v1 x, v2 y) {
  v1 m=x;
  v2 n=y;
  system.out.println ("this point is:" + m + "," + n);
}

Generic interface

You can also define generic interfaces in java.I wo n’t repeat them here,Just give example code:

public class demo {
  public static void main (string arsg []) {
    info<string>obj=new infoimp<string>("www.weixueyuan.net");
    system.out.println ("length of string:" + obj.getvar (). length ());
  }
}
//Define a generic interface
interface info<t>{
  public t getvar ();
}
//Implement the interface
class infoimp<t>implements info<t>{
  private t var;
  //define a generic constructor
  public infoimp (t var) {
    this.setvar (var);
  }
  public void setvar (t var) {
    this.var=var;
  }
  public t getvar () {
    return this.var;
  }
}

operation result:

length of string:18

Type erase

If no data type is specified when using generics,Then the generic type will be erased,Look at the following code:

public class demo {
  public static void main (string [] args) {
    point p=new point ();//type erase
    p.setx (10);
    p.sety (20.8);
    int x=(integer) p.getx ();//downcast
    double y=(double) p.gety ();
    system.out.println ("this point is:" + x + "," + y);
  }
}
class point<t1, t2>{
  t1 x;
  t2 y;
  public t1 getx () {
    return x;
  }
  public void setx (t1 x) {
    this.x=x;
  }
  public t2 gety () {
    return y;
  }
  public void sety (t2 y) {
    this.y=y;
  }
}

operation result:

this point is:10, 20.8

Because no data type is specified when using generics,In order not to make mistakes,The compiler will transform all the data up to object, so when you take out the coordinates and use it,This is no different than not using generics at the beginning of this article.

Limiting the types available for generics

In the above code,The type parameter can accept any data type,As long as it is defined.However, many times we only need a part of the data type,Users passing other data types may cause errors.For example, write a generic function to return the maximum value in an array of different types (integer array, double array, character array, etc.):

public<t>t getmax (t array []) {
  t max=null;
  for (t element:array) {
    max=element.doublevalue ()>max.doublevalue ()?element:max;
  }
  return max;
}

The above code will report an error,doublevalue () is a method of number class,Not all classes have this method,So we want to restrict the type parameter t so that it can only accept number and its subclasses (integer, double, character, etc.).

You can restrict the type of a generic type with the extends keyword.Improve the above code:

public<t extends number>t getmax (t array []) {
  t max=null;
  for (t element:array) {
    max=element.doublevalue ()>max.doublevalue ()?element:max;
  }
  return max;
}

<t extends number>means that t only accepts number and its subclasses,Incoming other types of data will report an error.The limitation here uses the keyword extends, which can be followed by a class or an interface.But here extends is no longer the meaning of inheritance,It should be understood that t is a type that inherits from the number class,Or t is a type that implements the xx interface.

Range of type parameters

In generics,Without limiting the type parameters,It can accept any data type,As long as it is defined.However, many times we only need a part of the data type,Users passing other data types may cause errors.For example, write a generic function to return the maximum value in an array of different types (integer array, double array, etc.):

public<t>t getmax (t array []) {
  t max=null;
  for (t element:array) {
    max=element.doublevalue ()>max.doublevalue ()?element:max;
  }
  return max;
}

The above code will report an error,doublevalue () is a method of class number and its subclasses,Not all classes have this method,So we want to restrict the type parameter t so that it can only accept number and its subclasses (integer, double, character, etc.).

The extends keyword can be used to limit the type of a generic type.Improve the above code:

public<t extends number>t getmax (t array []) {
  t max=null;
  for (t element:array) {
    max=element.doublevalue ()>max.doublevalue ()?element:max;
  }
  return max;
}

<t extends number>means that t only accepts number and its subclasses,Incoming other types of data will report an error.The limitation here uses the keyword extends, which can be followed by a class or an interface.If it is a class,Only oneBut there can be multiple interfaces,And separated by "&", such as<t extends interface1&interface2> ;.

The extends keyword is no longer the meaning of inheritance,It should be understood that t is a type that inherits from the number class,Or t is a type that implements the xx interface.

  • Previous In-depth analysis of the use of Java interfaces
  • Next Analysis of Insert Into Data Insertion in PHP + MySQL