Generic Type in j2se 5.0

Source: Internet
Author: User
Tags gety type casting uppercase letter
Generic Type in j2se 5.0 Author: Budi kurniawan Translation: rr00 Email: di_feng_ro@hotmail.com copyright statement: can be reproduced at will, reprint, please be sure to mark the original source of the article in the form of Hyperlink and author information and this statement
Original English address:
Http://www.onjava.com/pub/a/onjava/2005/07/06/generics.html
Chinese address:
Http://www.matrix.org.cn/resource/article/43/43634_java_generics.html
Keywords: Java generics java5

Summary
Generic is the most important feature of j2se 5.0. They allow you to write a type (class or interface) and create an instance by passing one or more reference types. This instance is limited to these types only. For example, java. util. List has been generalized in Java 5. When creating a list object, you can create a list instance by passing a Java type. This list instance can only act on the passed type. This means that if you pass a string, this list instance can only have a string object; if you pass an integer, this instance can only store integer objects. In addition to creating parameterized types, you can also create parameterized functions.
The first advantage of generics is strict type check during compilation. This is the most important feature of a collection framework. In addition, generics eliminate the vast majority of type conversions. Before JDK 5.0, when you use the collection framework, you have to perform type conversion.
This article will teach you how to operate generics. Its first part is "Days Without generics". Let's recall the inconvenience caused by older JDK versions. Then, let's take some generic examples. After discussing the syntax and the use of bounded generics, the last chapter explains how to write generics.

Days Without generics
All Java classes are sourced from Java. Lang. object, which means that all Java objects can be converted to objects. Therefore, in the previous JDK version, many functions of the Collection framework accept an object parameter. Therefore, collections is a multi-purpose tool that can hold any object, but it has adverse consequences.

For example, in a previous version of JDK 5.0, the Add function of the List class accepts an object parameter:

public boolean add(java.lang.Object element)

So you can pass any type to add. This was designed on purpose. Otherwise, it can only pass a specific object, and various list types will appear, such as stringlist, employeelist, and Addresslist.
Adding passing through objects can bring benefits. Now let's consider the get function (returning an element in the list). The following is the definition of JDK 5 earlier:

public java.lang.Object get(int index) throws IndexOutOfBoundsException

Get returns an object. Unfortunately, this starts. If you store two string objects in a list:

List stringList1 = new ArrayList();
stringList1.add("Java 5");
stringList1.add("with generics");

When you want to get an element from stringlist1, you get an object. to manipulate the original type element, You have to convert it to a string.

String s1 = (String) stringList1.get(0);

However, if you add a non-String object to stringlist1, the above Code will throw a classcastexception. with generics, you can create a list instance for a single purpose. for example, you can create a list instance that only accepts string objects, and the other instance can only accept the employee object. this applies to other types in the Collection framework.

Entry to generics

Like a function that can accept parameters, a generic function can also accept parameters. this is why a generic type is often called a parameterized type. however, unlike the function that uses () to pass parameters, generics use <> to pass parameters. declaration of a generic type and a general class are no different, except that you put the generic variables in <>.
For example, in JDK 5, you can declare a java. util. List: List <E> mylist;
E is called a type variable. this means that a variable will be replaced by a type. the value of the alternative type variable is treated as a parameter or return type. for the list interface, after an instance is created, e is treated as a parameter of ADD or other functions. E also causes the get or other parameters to return values. the following are definitions of ADD and get:

boolean add<E o>
E get(int index)

Note: A generic type allows you to pass a specific type variable during declaration or demonstration: E. in addition, if E is a class, you can pass the subclass; if E is an interface, you can pass the class that implements the interface;

----------------------------- Add a translator --------------------
List <number> numberlist = new arraylist <number> ();
Numberlist. Add (1, 2.0 );
Numberlist. Add (2 );
----------------------------- Add a translator --------------------

If you pass a string to a list, for example:

List<String> myList;

The add function of mylist accepts a string as its parameter, and the get function returns a string. Because a specific type is returned, no type conversion is required.

Note: By convention, we use a unique big writing object to represent a type variable. To create a generic type, you must pass the same parameter list during declaration. For example, if you want to create an arraylist to operate the string, you must put the string in <>. For example:

List<String> myList = new ArrayList<String>();

For example, java. util. MAP is defined as follows:

public interface Map<K,V>

K is used to declare the map key type, and V is used to represent the value type. Put and values are defined as follows:

V put(K key, V value)
Collection<V> values()

Note: A generic type is not directly or indirectly a subclass of Java. Lang. throwable. Because exceptions are thrown at runtime, it is impossible to predict what types of exceptions will be thrown during compilation.

The example in List 1 compares the differences between list in JDK 1.4 and JDK.

package com.brainysoftware.jdk5.app16;
import java.util.List;
import java.util.ArrayList;

public class GenericListTest {
  public static void main(String[] args) {
    // in JDK 1.4
    List stringList1 = new ArrayList();
    stringList1.add("Java 1.0 - 5.0");
    stringList1.add("without generics");
    // cast to java.lang.String
    String s1 = (String) stringList1.get(0);
    System.out.println(s1.toUpperCase());

    // now with generics in JDK 5
    List<String> stringList2 = new ArrayList<String>();
    stringList2.add("Java 5.0");
    stringList2.add("with generics");
    // no need for type casting
    String s2 = stringList2.get(0);
    System.out.println(s2.toUpperCase());
  }
}

In list 1, stringlist2 is a generic type. The declaration list <string> tells the compiler list instance to accept a String object. Of course, in other cases, you can create a list instance that can accept various objects. Note: When a member element is returned from the list instance, no object conversion is required because it returns the type you want, that is, String.

Note: Generic Type check is completed during compilation.

The most interesting thing is that a generic type is a type and can be treated as a type variable. For example, if you want your list to store lists of strings, you can declare the list by using list <string> as its type variable. For example:

List<List<String>> myListOfListsOfStrings;

To retrieve the string from the first list in mylist, you can use the following method:

String s = myListOfListsOfStrings.get(0).get(0);

The listofliststest class in the next list demonstrates that a list (named listoflists) accepts a string list as a parameter.

package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;
public class ListOfListsTest {
  public static void main(String[] args) {
    List<String> listOfStrings = new ArrayList<String>();
    listOfStrings.add("Hello again");
    List<List<String>> listOfLists = new ArrayList<List<String>>();
    listOfLists.add(listOfStrings);
    String s = listOfLists.get(0).get(0);
    System.out.println(s); // prints "Hello again"
  }
}

In addition, a generic type accepts one or more type variables. For example, java. util. MAP has two types of variable S. The first defines the key type and the second defines the value type. The following example shows how to use a generic map.

package com.brainysoftware.jdk5.app16;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<String, String>();
    map.put("key1", "value1");
    map.put("key2", "value2");
    String value1 = map.get("key1");
  }
}

In this example, we obtain the string value represented by key1 again without any type conversion.

Use generics without Parameters

Since the Collection types in j2se 5.0 have been generic, what would be the original code to use these types? Fortunately, they will continue to work in Java 5 because you can use generics without parameters. For example, you can continue to use the list interface as before, just as in the following example.

List stringList1 = new ArrayList();
stringList1.add("Java 1.0 - 5.0");
stringList1.add("without generics");
String s1 = (String) stringList1.get(0);

A generic type without any parameters is called a prototype ). It means that the code written for jdk1.4 or earlier will continue to work in Java 5.

Even so, one thing to note is that the JDK 5 compiler wants you to use generics with parameters. Otherwise, the compiler will prompt a warning because he thinks you may have forgotten to define the type variable S. For example, when compiling the above Code, you will see the following warnings, because the first list is considered as a prototype.

Note: COM/brainysoftware/jdk5/app16/genericlisttest. Java
Uses unchecked or unsafe operations.
Note: recompile with-xlint: unchecked for details.

If you don't want to see these warnings when using the prototype, you have several options to achieve your goal:
1. Compile with the parameter-source 1.4
2. Use @ supresswarnings ("unchecked") to comment
3. Update your code. instances using list <Object>. List <Object> can accept any type of objects, just like a prototype list. However, the compiler does not report errors.

Use? Wildcard
As mentioned above, if you declare a list <Atype>, this list applies to Atype, so you can store the following types of objects:
1. An Atype instance
2. Its subclass instance (if Atype is a class)
3. class instance implementing the Atype interface (if Atype is an interface)
However, note that a generic type is a Java type, Just Like java. Lang. string or Java. Io. File. You can create different Java types by passing different type variables to the generic type. For example, in the following example, list1 and list2 reference different types of objects.

List<Object> list1 = new ArrayList<Object>();
List<String> list2 = new ArrayList<String>();

List1 points to a list whose type variable S is Java. Lang. objects, while list2 points to a list whose type variable S is string. Therefore, passing a list <string> to a function with the list <Object> parameter will cause a compile time error. The following list can be explained:

Package com. brainysoftware. jdk5.app16;
Import java. util. arraylist;
Import java. util. List;

Public class allowedtypetest {
Public static void doit (list <Object> L ){
}
Public static void main (string [] ARGs ){
List <string> mylist = new arraylist <string> ();
// An error will be generated here
Doit (mylist );
}
}

The above Code cannot be compiled because you try to pass an incorrect type to the function doit. The doit parameter is list <Object>. The parameter you pass is list <string>.
Available? Wildcards solve this problem. List <?> It means a list that takes effect on any object. Therefore, doit can be changed:

public static void doIt(List<?> l) {}

In some cases, do you want to use it? Wildcard. For example, you have a printlist function that prints all the members of a list. When you want this function to take effect on any type of list. Otherwise, you can only write many printlist overload functions. The following list references the usage? The printlist function of the wildcard.

package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;

public class WildCardTest {

  public static void printList(List<?> list) {
    for (Object element : list) {
      System.out.println(element);
    }
  }
  public static void main(String[] args) {
    List<String> list1 = new ArrayList<String>();
    list1.add("Hello");
    list1.add("World");
    printList(list1);

    List<Integer> list2 = new ArrayList<Integer>();
    list2.add(100);
    list2.add(200);
    printList(list2);
  }
}

The Code indicates that in the printlist function, list <?> List objects of various types. However, please note that it should be used in the declaration? The wildcard is invalid, as shown in the following code:

List <?> Mylist = new arraylist <?> (); // Illegal

If you want to create a list that receives any type of objects, you can use the object as the type variable, as shown in the following code:

List<Object> myList = new ArrayList<Object>();

Use a boundary wildcard in a function
In the previous chapter, you learned to create generics of different Java types by passing different type variables S, but do not consider the inheritance relationship between type variables S. In many cases, you want a function to have different LIST parameters. For example, if you have a function getaverage, it returns the average value of a list member. However, if you use list <number> as the getaverage parameter, you cannot pass the list <integer> or list <double> parameter, because list <number> and list <integer> and list <double> are not of the same type.

You can use a prototype or a wildcard, but you cannot perform a security type check during compilation because you can pass any type of list, such as list <string> instances. You can use list <number> as the parameter, but you can only pass list <number> to the function. However, this will reduce your function functionality, because you may need to operate list <integer> or list <long> more than list <number>.

J2se5.0 adds a rule to solve this constraint. This rule allows you to define a upper bound variable. in this way, you can pass a type or its subclass. In the preceding getaverage function example, you can pass a list <number> or its subclass instance, such as list <integer> or list <float>.

The syntax of the upper-bound rule is defined as: generictype <? Extends upperboundtype>. For example, you can write list <? Extends number>. The following example shows how to use this rule.

package com.brainysoftware.jdk5.app16;
import java.util.ArrayList;
import java.util.List;
public class BoundedWildcardTest {
  public static double getAverage(List<? extends Number> numberList)
  {
    double total = 0.0;
    for (Number number : numberList)
      total += number.doubleValue();
    return total/numberList.size();
  }

  public static void main(String[] args) {
    List<Integer> integerList = new ArrayList<Integer>();
    integerList.add(3);
    integerList.add(30);
    integerList.add(300);
    System.out.println(getAverage(integerList)); // 111.0
    List<Double> doubleList = new ArrayList<Double>();
    doubleList.add(3.0);
    doubleList.add(33.0);
    System.out.println(getAverage(doubleList)); // 18.0
  }
}

The getaverage function in the preceding example allows you to pass a list <number> or a type variable to the list of any Java. Lang. Number subclass.

Lower Bound rules
The keyword extends defines the upper bound of A type variable. By using the super keyword, we can define the lower bound of A type variable, although not many cases are used. For example, if the parameter of a function is list <? Super integer>, which means that you can pass a list <integer> instance or any Java. Lang. Integer superclass ).

Create a generic

The previous section describes how to use generics, especially classes in the Collection framework. Now we start to learn how to write our own generics.

Basically, apart from declaring the type variable s you want to use, a generic type is no different from other classes. These type variables are located in <> behind the type. For example, the following point is a generic type. A point object represents a point in a system. It has abscissa and ordinate. By enabling point generics, you can define the precision of a point instance. For example, if a point object needs to be very precise, you can use double as the type variable. Otherwise, integer is enough.

package com.brainysoftware.jdk5.app16;
public class Point<T> {
  T x;
  T y;
  public Point(T x, T y) {
    this.x = x;
    this.y = y;
  }
  public T getX() {
    return x;
  }
  public T getY() {
    return y;
  }
  public void setX(T x) {
    this.x = x;
  }
  public void setY(T y) {
    this.y = y;
  }
}

In this example, T is the type variable of point. T is the return value type of getx and Gety, and is also the parameter type of setx and sety. In addition, the constructor combines two T parameters.
The Point class is the same as other classes. For example, the following example creates two point objects: ponint1 and point2. The former uses Integer as the type variable, while the latter uses double as the type variable.

Point<Integer> point1 = new Point<Integer>(4, 2);
point1.setX(7);
Point<Double> point2 = new Point<Double>(1.3, 2.6);
point2.setX(109.91);

Summary
Generics enable the code to have stricter type checks during compilation. Generic has two roles, especially in the Collection framework. First, they added a type check for the collection type during compilation, so the types that the collection class can hold have a restriction on the parameter types passed to it. For example, if you create a java. util. List instance that holds strings, it cannot accept integers or other types. Second, when you get an element from a set, generics eliminate the need for type conversion.
Generics can be used without type variables, for example, as a prototype. These measures enable the code before Java 5 to run in JRE 5. However, for new applications, you 'd better not use the prototype, Because Java may not support them in the future.

You already know that different Java types can be generated by passing different types of type variables to generics. That is to say, the types of list <string> and list <Object> are different. Although string is Java. Lang. object. However, passing a list <string> to a function with the list <Object> parameter produces a compilation error (compile error ). Can a function be used? Wildcards allow them to accept parameters of any type. List <?> Indicates any type of object.
Finally, you can see that there is no difference between writing a generic type and other general Java classes. You only need to declare a series of type variables in <> behind the type name. S is the return value type or parameter type. By convention, a type variable is represented by an uppercase letter.

 

 
Tags:

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.