Java2_Java generic, java2_java generic

Source: Internet
Author: User

Java2_Java generic, java2_java generic

I.Introduction of generic concepts (Why do generic concepts need to be proposed )?

First, let's take a look at the following short code:

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4         List list = new ArrayList(); 5         list.add("qqyumidi"); 6         list.add("corn"); 7         list.add(100); 8  9         for (int i = 0; i < list.size(); i++) {10             String name = (String) list.get(i); // 111             System.out.println("name:" + name);12         }13     }14 }

Defines a set of List types. First, two string types are added to the set, and then an Integer type value is added. This is completely allowed, because the default list type is the Object type. In the subsequent loop, an error similar to // 1 may easily occur because you forget to add an Integer value or other encoding to the list. Because the compilation phase is normal, the "java. lang. ClassCastException" exception will occur during the runtime. Therefore, it is difficult to find such errors during encoding.

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

1. when we put an Object into the set, the set does not remember the Object type. When we retrieve this Object from the set again, the compilation type of the Object is changed to the Object type, however, its runtime type is its own type.

2. Therefore, when a collection element is retrieved at // 1, the human type must be forcibly converted to the specific target type, and the "java. lang. ClassCastException" exception may easily occur.

Is there any way to enable the set to remember the various types of elements in the set and avoid the "java. lang. ClassCastException" exception during runtime as long as there is no problem during compilation? The answer is to use generics.

 

2. What is generic?

Generic, that is, "parameterized 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 ).

It seems a little complicated. First, let's look at the above example using generic writing.

1 public class GenericTest {2 3 public static void main (String [] args) {4/* 5 List list = new ArrayList (); 6 list. add ("qqyumidi"); 7 list. add ("corn"); 8 list. add (100); 9 */10 11 List <String> list = new ArrayList <String> (); 12 list. add ("qqyumidi"); 13 list. add ("corn"); 14 // list. add (100); // 1 indicates a compilation error of 15 16 for (int I = 0; I <list. size (); I ++) {17 String name = list. get (I); // 218 System. out. println ("name:" + name); 19} 20} 21}

After the generic method is used, a compilation error occurs when you want to add an Integer type object at // 1. The List <String>, the list set can only contain elements of the String type, so that forced type conversion is not required at // 2. At this time, the set can remember the type information of the element, the compiler can confirm that it is of the String type.

Based on the above generic definition, we know that in List <String>, String is a type real parameter, that is, the corresponding List interface must contain a type parameter. In addition, the result returned by the get () method is also of this parameter type (that is, the input type of the parameter ). Next let's take a look at the specific definition of the List interface:

 1 public interface List<E> extends Collection<E> { 2  3     int size(); 4  5     boolean isEmpty(); 6  7     boolean contains(Object o); 8  9     Iterator<E> iterator();10 11     Object[] toArray();12 13     <T> T[] toArray(T[] a);14 15     boolean add(E e);16 17     boolean remove(Object o);18 19     boolean containsAll(Collection<?> c);20 21     boolean addAll(Collection<? extends E> c);22 23     boolean addAll(int index, Collection<? extends E> c);24 25     boolean removeAll(Collection<?> c);26 27     boolean retainAll(Collection<?> c);28 29     void clear();30 31     boolean equals(Object o);32 33     int hashCode();34 35     E get(int index);36 37     E set(int index, E element);38 39     void add(int index, E element);40 41     E remove(int index);42 43     int indexOf(Object o);44 45     int lastIndexOf(Object o);46 47     ListIterator<E> listIterator();48 49     ListIterator<E> listIterator(int index);50 51     List<E> subList(int fromIndex, int toIndex);52 }

We can see that after the List interface adopts the generic definition, E in <E> indicates the type parameter, and can receive the specific type real parameters. In this interface definition, where E exists, it indicates that the same real parameters of the external type are accepted.

Naturally, ArrayList serves as the implementation class of the List interface. Its definition form is:

1 public class ArrayList <E> extends actlist <E> 2 implements List <E>, RandomAccess, Cloneable, java. io. serializable {3 4 public boolean add (E e) {5 ensureCapacityInternal (size + 1); // Increments modCount !! 6 elementData [size ++] = e; 7 return true; 8} 9 10 public E get (int index) {11 rangeCheck (index); 12 checkForComodification (); 13 return ArrayList. this. elementData (offset + index); 14} 15 16 //... omit other specific definition processes 17 18}

From the source code point of view, we understand why the compilation error of the Integer type object is added at // 1, and the type of get () at // 2 is the String type.

 

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

From the above content, we have understood the specific operation process of generics. You also know that interfaces, classes, and methods can also be defined using generics and their corresponding usage. Yes. In actual use, it can be divided into generic interfaces, generic classes, and generic methods.

The 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 a simple generic class and method definition:

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         System.out.println("name:" + name.getData()); 7     } 8  9 }10 11 class Box<T> {12 13     private T data;14 15     public Box() {16 17     }18 19     public Box(T data) {20         this.data = data;21     }22 23     public T getData() {24         return data;25     }26 27 } 

During the definition of generic interfaces, generic classes, and generic methods, common parameters such as T, E, K, and V are often used to represent generic parameters, because it receives the type arguments passed in from external users.Is the type of the corresponding object instance generated for different input type parameters the same?

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         Box<Integer> age = new Box<Integer>(712); 7  8         System.out.println("name class:" + name.getClass());      // com.qqyumidi.Box 9         System.out.println("age class:" + age.getClass());        // com.qqyumidi.Box10         System.out.println(name.getClass() == age.getClass());    // true11 12     }13 14 }

As a result, we found that while using generic classes, although different generic real parameters are passed in, different types are not actually generated, there is only one generic class for passing in different generic arguments in the memory, that is, the original most basic type (Box in this instance). Of course, logically, we can think of multiple different generic types.

The reason is that the concept of generics in Java is proposed for the purpose, which only acts on the code compilation stage. During the compilation process, the information about the generic type is erased. That is to say, the compiled class file does not contain any generic information. The generic information does not enter the runtime stage.

This is summarized as one sentence: generic types are logically considered to be multiple different types, but they are actually the same basic types.

 

4. Type wildcard

The above conclusion shows that both Box <Number> and Box <Integer> are actually Box types. Now we need to continue to discuss a problem. Logically, can I think of Box <Number> and Box <Integer> as a generic type with parent-child relationship?

To solve this problem, let's continue to look at the following example:

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<Number> name = new Box<Number>(99); 6         Box<Integer> age = new Box<Integer>(712); 7  8         getData(name); 9         10         //The method getData(Box<Number>) in the type GenericTest is 11         //not applicable for the arguments (Box<Integer>)12         getData(age);   // 113 14     }15     16     public static void getData(Box<Number> data){17         System.out.println("data :" + data.getData());18     }19 20 }

The error message "The method getData (Box <Number>)" is displayed in The Code // 1) in the t ype GenericTest is not applicable for the arguments (Box <Integer> ). Obviously, with the prompt information, we know that Box <Number> cannot be regarded as the parent class of Box <Integer> logically. So what is the reason?

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<Integer> a = new Box<Integer>(712); 6         Box<Number> b = a;  // 1 7         Box<Float> f = new Box<Float>(3.14f); 8         b.setData(f);        // 2 9 10     }11 12     public static void getData(Box<Number> data) {13         System.out.println("data :" + data.getData());14     }15 16 }17 18 class Box<T> {19 20     private T data;21 22     public Box() {23 24     }25 26     public Box(T data) {27         setData(data);28     }29 30     public T getData() {31         return data;32     }33 34     public void setData(T data) {35         this.data = data;36     }37 38 }

In this example, an error message is displayed at // 1 and // 2. Here we can use the reverse verification method to describe.

Assume that Box <Number> can be regarded as the parent class of Box <Integer> logically, no error is prompted at // 1 and // 2, and the problem arises, what type of data is retrieved using the getData () method? Integer? Float? Or Number? In addition, the order in the programming process is not controllable, so when necessary, you must determine the type and perform forced type conversion. Obviously, this is in conflict with the concept of generics. Therefore,Logically, Box <Number> cannot be regarded as the parent class of Box <Integer>.

Well, let's go back and look at the first example of "type wildcard". We know the underlying cause of the specific error message. How can this problem be solved? The Headquarters can define a new function. This is obviously against the polymorphism concept in Java. Therefore, we need a reference type that can be logically used to represent both the Box <Integer> and Box <Number> parent classes. As a result, the type wildcard came into being.

What is a type wildcard? Replace the actual type of arguments. Note that this is a type parameter, not a type parameter! And Box <?> Logically, Box <Integer> and Box <Number>. Therefore, we can still define generic methods to meet such requirements.

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         Box<Integer> age = new Box<Integer>(712); 7         Box<Number> number = new Box<Number>(314); 8  9         getData(name);10         getData(age);11         getData(number);12     }13 14     public static void getData(Box<?> data) {15         System.out.println("data :" + data.getData());16     }17 18 }

Sometimes, we may hearUpper Limit of Type wildcard and lower limit of Type wildcard. What is it like?

In the above example, if you need to define a function similar to the getData () method, but there are further restrictions on the type of real parameters: only the Number class and its subclass can be used. In this case, the upper limit of the type wildcard is required.

 1 public class GenericTest { 2  3     public static void main(String[] args) { 4  5         Box<String> name = new Box<String>("corn"); 6         Box<Integer> age = new Box<Integer>(712); 7         Box<Number> number = new Box<Number>(314); 8  9         getData(name);10         getData(age);11         getData(number);12         13         //getUpperNumberData(name); // 114         getUpperNumberData(age);    // 215         getUpperNumberData(number); // 316     }17 18     public static void getData(Box<?> data) {19         System.out.println("data :" + data.getData());20     }21     22     public static void getUpperNumberData(Box<? extends Number> data){23         System.out.println("data :" + data.getData());24     }25 26 }

In this case, an error message is displayed when calling code // 1, while calling at // 2 // 3 is normal.

The upper limit of the type wildcard is shown inBox <? Extends Number> format definition,Correspondingly, the lower limit of the type wildcard is Box <? Super Number> format. Its meaning is the opposite to the upper limit of the type wildcard..

 

5. Additional Words

The examples in this article are simply cited to illustrate some ideas in generics, and do not necessarily have practical availability. In addition, when it comes to generics, I believe that the most common application is in the collection. In fact, in the actual programming process, you can use generics to simplify development, and can ensure the quality of the Code.It is worth noting that there is no so-called generic array in Java.

For generics, the most important thing is to understand the ideas and objectives behind them.

 

6. Original article link

Java summary series: java generics

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.