Comprehensive parsing of generics in Java

Source: Internet
Author: User
Tags comparable

Java generics ( generics ) is a new feature introduced in JDK 5 that allows for the use of type parameters (types parameter) when defining classes and interfaces. The declared type parameter is replaced with a specific type when used. The most important application of generics is in the new collection class framework in JDK 5. For the introduction of generic concepts, the development Community's view is mixed. On the good side, the introduction of generics can solve the runtime type errors that the previous collection class framework would normally have in use, because the compiler can find many obvious errors at compile time. In the never-so-good place, there are some less elegant implementations of Java generics to ensure compatibility with older versions. This is, of course, the historical burden of any historical programming language. Subsequent versions of the update will be tired of earlier design flaws.

When using generics, developers can easily make mistakes based on their intuition. For example, if a method is received List<Object> as a formal parameter, then if you try to List<String> pass an object as an actual argument, you find that it cannot be compiled. Although it is intuitively that object is the parent of string, this type conversion should be reasonable. In practice, however, this creates an implicit type conversion problem, so the compiler directly prohibits such behavior. This article attempts to make a general description of Java generics.

Type Erase

The first prerequisite for a proper understanding of the generic concept is to understand type erasure ( type erasure ).

Generics in Java are basically implemented at the compiler level. In the generated Java byte code, the type information in generics is not included. When you use generics, the type parameters are removed by the compiler at compile time. This process is called type erasure. As defined in the code List<Object> and the List<String> type, after compilation will become a list. The JVM sees only the list, and the type information appended by generics is not visible to the JVM. The Java compiler will try to identify possible errors at compile time, but there is still no way to avoid a type conversion exception at run time. Type erasure is also an important difference between the generic implementation of Java and the way the C + + template mechanism is implemented. Many of the strange features of generics are related to the existence of this type of erasure, including:

list<string>.class or list<integer>.class , and only List.class . A static variable is shared by all instances of the generic class. For classes declared as Myclass<t> , the method of accessing static variables in them is still myclass.mystaticvar. Either through new Myclass<string>; or new Myclass<integer> creates an object that shares a static variable. A generic type parameter cannot be used in a catch statement for Java exception handling. Because exception handling is performed by the JVM at run time. Because the type information is erased, the JVM is unable to distinguish between two exception types myexception<string>; and Myexception<integer> . For the JVM, they are all myexception types. You cannot execute a catch statement that corresponds to an exception.

is simpler: First, find the specific class that replaces the type parameter. This specific class is generally object. If the upper bound of the type parameter is specified, the upper bound is used. Replace the type parameters in the code with the specific classes. Also remove the occurrence of the type declaration, that is, the contents of <> . For example:   T Get () method declaration becomes Object get () ;   list<string> becomes List . Next you may need to generate some bridging method (bridge methods). This is because the class after the erasure type may be missing some of the necessary methods. Consider the following code, for example:

Class MyString implements comparable<string> {public int compareTo (String str) {return 0; }}

When the type information is erased, the declaration of the above class becomes the class MyString implements comparable. However, the class mystring will have a compile error because there is no int compareTo (Object) method that implements the comparable declaration of the interface. This method is dynamically generated by the compiler at this time.

Example analysis

List<object> and List<string> as an example to specifically analyze:

 Public void inspect (list<object> list)  {         for  (object obj : list)  {                 system.out.println (obj);         }        list.add (1);  //This operation is valid in the context of the current method.  }public void test ()  {        List<String>  strs = new ArrayList<String> ();         Inspect (STRs);  //compilation error  } 

In this code, the inspect method accepts List<Object> as a parameter, and a test List<String> compilation error occurs when an attempt is made to pass in the method. Assuming this is allowed, the inspect method can be used list.add(1) to add a number to the collection. Thus, in the test method's view, List<String> a Integer type of object is added to the collection it is declared as. This is obviously a violation of the principle of type safety, and will certainly be thrown at some point ClassCastException . Therefore, the compiler prohibits such behavior. The compiler will check for possible types of security issues as much as possible. A compilation error is given where it is determined to violate the relevant principles. A warning message is given when the compiler cannot determine whether the type is being used correctly.

wildcard characters and upper and lower bounds

List<string> to declare that the specific type is String , or you can use a wildcard character ? To represent an unknown type, such as List<?> declares that the element type contained in list is unknown. Wildcard characters are actually a set of types, but the specific type is unknown. List<?> declares that all types are possible. But List<?> is not the same as List<object> . List<object> actually determines that the list contains object and its subclasses, which can be used with the object to make a reference. List<?> is the type of element it contains is indeterminate. This may contain a String , or Integer . If it contains a String , it is wrong to add an element of type Integer to it. Because the type is unknown, you cannot create a new ArrayList object by using the new Arraylist<?> () method. Because the compiler cannot know what the specific type is. However, for  , the element in List<?> can always be referenced with object because, although the type is unknown, it must be object and its subclasses. Consider the following code:

public void wildcard (list<> List) {list.add (1);//Compilation Error}

As shown above, there is always a compile error when trying to manipulate a generic class with wildcard characters. The reason for this is that the type represented by the wildcard is unknown.


Comprehensive parsing of generics in Java

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.