Java Summary Article series: Java generics detailed _java

Source: Internet
Author: User
Tags addall int size

I. The concept of generics (why generics are required)?

First, let's look at the short code below:

public class Generictest {public

  static void Main (string[] args) {
    list list = new ArrayList ();
    List.add ("Qqyumidi");
    List.add ("corn");
    List.add (m);

    for (int i = 0; i < list.size (); i++) {
      String name = (String) list.get (i);//1
      System.out.println ("Name:" + N AME);}}

Defines a collection of list types, in which two string-type values are added, followed by a value of an integer type. This is entirely permissible because the list default type is type Object. In subsequent loops, it is easy to have errors similar to those in//1 because you have added an integer value or other encoding reason to the list before you forget it. Because the compile phase is normal, a "java.lang.ClassCastException" exception appears at run time. As a result, this type of error encoding is not easy to find.

In the coding process as above, we found that there are two main problems:

1. When we put an object into the collection, the collection does not remember the type of this object, and when this object is fetched again from the collection, the modified object's compilation type becomes type Object, but its run-time type is still its own type.

2. As a result, it is necessary to//1 the collection elements to the specific target type, and the "java.lang.ClassCastException" exception can easily occur.

So is there any way to make the collection can remember the types of elements in the collection, and can achieve as long as the compile without problems, the runtime will not appear "Java.lang.ClassCastException" Exception? The answer is to use generics.

Two. What is generics?

Generics, or "parameterized type." When referring to a parameter, the most familiar is the physical parameter when the method is defined, and then the argument is passed when this method is called. So how does a parameterized type understand? As the name suggests, the type is parameterized by the original specific type, similar to the variable parameter in the method, where the type is defined as a parameter form (which can be called a type parameter) and then passed into the specific type (the type argument) at the time of use/invocation.

Looks like a bit complicated, first of all, let's take a look at the example above using the generic type.

public class Generictest {public

  static void Main (string[] args) {/
    *
    List list = new ArrayList ();
    List.add ("Qqyumidi");
    List.add ("corn");
    List.add (m);
    * *

    list<string> List = new arraylist<string> ();
    List.add ("Qqyumidi");
    List.add ("corn");
    List.add (m);  1 hint compile error for

    (int i = 0; i < list.size (); i++) {
      String name = List.get (i);//2
      System.out.println (" Name: "+ name);}}}

When a generic type is written, a compile error occurs when//1 wants to join an integer object, and by List<string>, the list can be directly qualified to contain only String elements, thereby eliminating the need for coercion of type conversions at//2, because at this point , the collection remembers the type information of the element, and the compiler has been able to confirm that it is a string type.

In conjunction with the above generic definition, we know that in list<string>, String is a type argument, that is, the corresponding list interface must contain a type parameter. The return result of the Get () method is also directly the parameter type (that is, the corresponding incoming type argument). Here's a look at the specific definition of the list interface:

 public interface list<e> extends {int size ();

  Boolean IsEmpty ();

  Boolean contains (Object O);

  Iterator<e> iterator ();

  Object[] ToArray ();

  <T> t[] ToArray (t[] a);

  Boolean Add (e e);

  Boolean remove (Object O);

  Boolean containsall (collection<?> c);

  Boolean AddAll (collection< extends e> c);

  Boolean addall (int index, COLLECTION<? extends e> c);

  Boolean RemoveAll (collection<?> c);

  Boolean retainall (collection<?> c);

  void Clear ();

  Boolean equals (Object O);

  int hashcode ();

  E get (int index);

  e Set (int index, e element);

  void Add (int index, E element);

  E Remove (int index);

  int indexOf (Object o);

  int LastIndexOf (Object o);

  Listiterator<e> Listiterator ();

  listiterator<e> listiterator (int index);
list<e> sublist (int fromindex, int toindex); }

We can see that in the list interface, after the generic definition is adopted, the E in,<e> represents the type parameter, can receive the concrete type argument, and in this interface definition, wherever e appears, it represents the same type argument accepted from outside.

Naturally, ArrayList as the implementation class of the list interface, which is defined in the form of:

public class Arraylist<e> extends abstractlist<e> 
    implements List<e>, Randomaccess, Cloneable, java.io.Serializable {public
  
  boolean add (E e) {
    ensurecapacityinternal (size + 1);//increments modcount!!
    elementdata[size++] = e;
    return true;
  }
  
  Public E get (int index) {
    Rangecheck (index);
    Checkforcomodification ();
    return ArrayList.this.elementData (offset + index);
  }
  
  //... Omit the other specific definition process

}

Thus, we understand from the source code point of view why//1 Add an integer type Object compilation error, and//2 Place get () to type directly is string type.

Three. Custom generic interfaces, generic classes, and generic methods

From the above, we have already understood the specific operation process of generics. Also know that interfaces, classes, and methods can also be defined using generics, as well as the corresponding use. Yes, when used specifically, it can be divided into generic interfaces, generic classes, and generic methods.

Custom generic interfaces, generic classes, and generic methods are similar to the list and ArrayList in the Java source code above. As follows, let's look at one of the simplest generic classes and method definitions:

public class Generictest {public

  static void Main (string[] args) {

    box<string> name = new Box<string> ("corn");
    System.out.println ("Name:" + name.getdata ());
  }

}

Class Box<t> {

  private T data;

  Public box () {

  } public

  box (T data) {
    This.data = data
  }

  Public T GetData () {return
    data;
  }

}

In the definition of generic interfaces, generic classes, and generic methods, our common parameters, such as T, E, K, V, are often used to represent generic parameters, as they are received from type arguments passed in from outside use. So for different incoming type arguments, is the type of the corresponding object instance generated the same?

public class Generictest {public

  static void Main (string[] args) {

    box<string> name = new Box<string> ("corn");
    box<integer> age = new box<integer> (712);

    System.out.println ("Name class:" + Name.getclass ());   Com.qqyumidi.Box
    System.out.println ("Age class:" + Age.getclass ());    Com.qqyumidi.Box
    System.out.println (name.getclass () = = Age.getclass ());  True

  }

}

As a result, we found that when using generic classes, although a different generic argument is passed in, there is no real sense of generating different types, and a generic class passed in different generic arguments has only one memory, or the original most basic type (box in this case), of course, Logically we can understand several different generic types.

The reason is that the concept of generics in Java is proposed to causes it to only function in the code compilation phase, during compilation, for the correct validation of generic results, the generic information will be wiped out, that is, after the successful compilation of the class file does not contain any generic information. Generic information does not enter the Run-time phase.

To sum it up, a generic type is logically viewed as a number of different types, and is actually the same basic type.

Four. Type wildcard characters

The above conclusion, we know that,box<number> and box<integer> are actually Box types, now need to continue to explore a problem, then logically, similar to box<number> and box< Can integer> be considered a generic type with a parent-child relationship?

To figure this out, let's continue to look at the following example:

public class Generictest {public

  static void Main (string[] args) {

    box<number> name = new Box<number> (a);
    box<integer> age = new box<integer> (712);

    GetData (name);
    
    The method GetData (box<number>) in the type Generictest was 
    //not applicable for the arguments (box<integer& gt;)
    GetData (age);  1

  } public
  
  static void GetData (box<number> data) {
    System.out.println ("Data:" + data.getdata ()) ;
  }

}

We found that there was an error message at the code//1: The Method GetData (box<number>) in the T ype Generictest was not applicable for the arguments ( box<integer>). Obviously, by prompting the information, we know that box<number> is not logically considered a box<integer> parent class. So what is the reason?

public class Generictest {public

  static void Main (string[] args) {

    box<integer> a = new box<integer> ( 712);
    Box<number> B = A; 1
    box<float> f = new box<float> (3.14f);
    B.setdata (f);    2

  } public

  static void GetData (box<number> data) {
    System.out.println ("Data:" + data.getdata ()); c10/>}

class Box<t> {

  private T data;

  Public box () {

  } public

  box (T data) {
    setData (data);
  }

  Public T GetData () {return
    data;
  }

  public void SetData (T data) {
    This.data = Data
  }

}

In this example, it is obvious that//1 and//2 will be prompted incorrectly. Here we can use the contradiction to explain.

Assuming that box<number> can be logically considered as a box<integer> parent, then//1 and//2 will not have any errors, so the question comes up, what type of data is taken out of the GetData () method? An Integer? Float? or number? And because of the order in the programming process is not controllable, resulting in the need for type judgment, and forced type conversion. Obviously, this contradicts the idea of generics, so logically box<number> cannot be considered a box<integer> parent class.

OK, so let's go back and look at the first example in "type wildcard", and we know the underlying reason for its specific error hints. So how to solve it? The headquarters can redefine a new function. This is obviously a violation of the polymorphic idea in Java, so we need a reference type that logically can be used to represent the parent class at the same time as box<integer> and box<number>, from which the type wildcard character arises.

Type wildcard characters are generally used? Instead of a specific type argument. Note that here is the type argument, not the type parameter! And box<?> in logic is box<integer>, Box<number> The parent class for all box< specific type arguments >. As a result, we can still define generic methods to accomplish this type of requirement.

public class Generictest {public

  static void Main (string[] args) {

    box<string> name = new Box<string> ("corn");
    box<integer> age = new box<integer> (712);
    box<number> number = new box<number> ();

    GetData (name);
    GetData (age);
    GetData (number);
  }

  public static void GetData (box<?> data) {
    System.out.println ("Data:" + data.getdata ());
  }

Sometimes, we may also hear the upper bound of the type wildcard and the lower bounds of the type wildcard character. What is the specific one?

In the above example, if you need to define a method that functions like GetData (), there is a further restriction on the type argument: only the number class and its subclasses. At this point, you need to use the upper bound of the type wildcard character.

public class Generictest {public

  static void Main (string[] args) {

    box<string> name = new Box<string> ("corn");
    box<integer> age = new box<integer> (712);
    box<number> number = new box<number> ();

    GetData (name);
    GetData (age);
    GetData (number);
    
    Getuppernumberdata (name); 1
    getuppernumberdata (age);  2
    getuppernumberdata (number);//3
  } public

  static void GetData (box<?> data) {
    SYSTEM.OUT.PRINTLN ("Data:" + data.getdata ());
  }
  
  public static void Getuppernumberdata (BOX<? extends number> data) {
    System.out.println ("Data:" + Data.getdata ());
  }

At this point, it is obvious that an error is invoked at the//1 of the code and the//2//3 call is normal.

The upper bound of the type wildcard character is shaped like box<? Extends number> form definition, corresponding to the lower limit of type wildcard is box<? The Super number> form, whose meaning is the opposite of the upper limit of the type wildcard, does not make too much elaboration here.

Five. The words outside the article

The examples in this article are simply cited to illustrate some of the ideas in generics and do not necessarily have actual usability. In addition, a reference to generics, I believe that we use the most is in the collection, in fact, in the actual programming process, they can use generics to simplify development, and can be a good guarantee of code quality. Also note that there is no so-called generic array in Java.

For generics, the most important thing is to understand the thought and purpose behind it.

The above is a small set for everyone to bring the Java Summary series: Java generic details of all the content, I hope to help you, a lot of support cloud Habitat Community ~

Related Article

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.