Generic constraints and restrictions for Java

Source: Internet
Author: User
Tags comparable throwable wrapper

Type parameters cannot be instantiated with a base type

You cannot replace a base type with a type parameter: for example, there is no pair<double>, only pair<double> The reason is the type erase. After erasing, the pair class contains a field of type Object , and object cannot store a double value. This embodies the independent state of the basic types in the Java language.

Run-time type queries are only available for original types (raw type)

runtime : Usually refers to the time the JVM executes after ClassLoader is loaded

type query : instanceof, GetClass, coercion type conversion

Primitive Type : that is (raw type), the generic type is erased by the compiler type as a qualified type of object or generic parameter (for example, Pair<t extends Comparable> Comparable is the limited type of T, the original type of the generic is comparable, so the pair class without generics is pair<comparable>), that is, the pair class contains the comparable type of domain

There is no generic type in the JVM

eg

 if (a instanceof pair<string>) //error, test only if a is any type of pair, you will see the compiler ERROR warning if (A Span style= "color: #0000ff;" >instanceof pair<t>) //errorpair<string> p = (pair<string>) A; //warning, test only if a is a pair pair<string> stringpair = ...; pair<employee> employeepair = ...; if (stringpair.getclass () = = Employeepair.getclass ())  will get true because two calls to GetClass will return Pair.class       

Cannot create an array of parameterized types (generic array)

array of parameterized types : refers to an array of types with generic parameters, also known as generic arrays, such as pair<t>[], t[]

You cannot instantiate an array of parameterized types, for example:

ERROR

Here we assume that we can instantiate, then after the compiler type is erased, the type of table is pair[], and we'll make it covariant to object[]:

object[] Objarray = table;

In general, the array remembers his element type pair, and if we try to store other types of elements , we throw an exception ( array store check ), for example:

error--component type is Pair

However, for generic type pair<string>, a type wipe invalidates this different class-checking mechanism, which is why you cannot instantiate a generic array !

New Pair<employee> ();  //If the generic mechanism allows us to instantiate an array, there is no reason for this step to go wrong! And that goes against our original purpose. (limited type)
    • The array store only checks the erased type , and because the Java language Design array can be covariant , you can compile
    • Ability to check through array storage , but still result in a type error, so it is not allowed to create an array of parameterized types
    • Note that variables that declare type pair<string>[] are legitimate, but they cannot be created (we should use new pair<string>[10]{directly ...} To initialize this variable)

indirect implementations of generic arrays :

Through the generic array wrapper, such as the ArrayList class, maintains an object array, then restricts the type through the import and export method set, get, and casts the array type, thereby indirectly implementing the generic array,

such as:arraylist:arraylist<pair<t>>, arraylist<t>

Cannot instantiate type variable t

  • That is, you cannot use a type variable in an expression such as new T (..), New t[.], or T.class
    • For example: Public Pair () {first = new T ();}//error! type erase changes t to object, calling the non-intended new object ()
  • cannot use new T (..)
    • However, you can call the Class.newinstance method through reflection to construct a generic object (note that the expression T.class is illegal)
    •  public  Static <T> pair<t> Makepair (class<t> cl) {try{return new pair<> catch (Exception ex) {return null//class);               
    • Note: Class classes themselves are generic. String.class is an example of a class<string> , so the Makepair method can infer the type of pair
  • cannot use new t[...]
    • That is, you cannot (directly) create a generic array, refer to my other blog post (http://www.cnblogs.com/ixenos/p/5648519.html), and do not repeat
    • solution: using generic array wrapper , for example ArrayList
      • However, when designing a generic array wrapper, such as method Minmax returns a t[] array, the generic array wrapper cannot be cast, because the type erase, return (T []) new object is meaningless and strong. At this point, we have to use reflection, call Array.newinstance:
      •  Import java.lang.reflect.*< Span style= "color: #000000;" >;... public static <t extends Comparable> t[] Minmax (T ... a) {t[] mm = (t[]) array.newinstance (A.getclass (). Getcomponenttype (), 2      
        • getcomponenttype () returns the   that represents the array component type; Class . If this class does not represent an array class, this method returns NULL.

    • and the implementation of the ToArray method in the ArrayList class is troublesome.
      • public object[] ToArray ()   No parameter, return to object[] array
         public< Span style= "color: #000000;" > object[] ToArray () {return arrays.copyof (elementdata    , size); }     
        •   "API Document description" public static <T> T []  copyOf  (t[] original,int newlength)  
          Copy the specified array, intercept or fill with null (if necessary) so that the copy has the specified length. For all indexes that are valid in both the original array and the replica, the two arrays will contain the same values. For all indexes that are valid in the replica and are not valid in the original array, the copy will contain null . These indexes exist when and only if the specified length is greater than the length of the original array. The resulting array and the original array belong to the exact same class.  
      • Public <T> t[] ToArray (t[] a) a -to store the t[] array of the list element (if it is large enough) otherwise assign a new array with the same run-time type , return the t[] array
      •  @SuppressWarnings ("Unchecked" ) public <T>  t[] ToArray (t[] a) {if (a.length < size) // make a new array of a ' s runtime type, BU T my contents: return (t[]) arrays.copyof (Elementdata, Size, A.getclass ()); A.getclass () The  run-time type of the run-time destination array  system.arraycopy (elementdata, 0, a, 0if (a.length > size) A[size] = nullreturn A;}        
          • "API Documentation description"
            copyOf (u[] Original,int newlength, class<? extends t[]> NewType)
            Copies the specified array, intercepts it, or fills it with null (if necessary) so that the copy has the specified length. For all indexes that are valid in both the original array and the replica, the two arrays will contain the same values. For all indexes that are valid in the replica and not valid in the original array, the copy will contain null. These indexes exist when and only if the specified length is greater than the length of the original array. The resulting array belongs to the NewType class.

Invalid type variable in static context of generic class

    • A generic class cannot reference a type variable in a static field or in a static method
    • Class singleton<t>{    ////ERROR}   
      • Only the Singleton class is left after the type erase, because it is static so he contains only one singleinstance domain, and if it can be run, the Singleton class will generate a different type of domain for the template, resulting in a conflict

Cannot throws or catch instances of generic classes (for exceptions)

  • Generic class inheritance Throwable class is illegal, such as public class Problem<t> extends Exception {...}//error cannot be compiled
  • A catch clause cannot use a type variable
  • void DoWork (class<t> T) {Try do work     }// ERROR Logger.global.info (...)}} 
  • However, it is permissible to use type variables in the exception specification:  
  • Try do work   }// capture to specific instance //at this time throw concrete instance, so throw T and throws T is possible  ! } 
    • This feature works by using generic classes, type erasure, and suppresswarnings annotations to eliminate checks for checked (checked) exceptions.
      • unchecked and checked exceptions : The Java language Specification refers to all exceptions that are sent to the error class or RuntimeException as an unchecked (unchecked) exception , and the others are checked ( Checked) Exception
      • Java Exception Handling principle : You must provide a single processor for all checked (checked) exceptions, that is, a pair of one, many-to- many
        @SuppressWarnings ("Unchecked")  ///suppresswarning labeling is critical so that the compiler considers t to be a unchecked exception and thus does not force the processor to be supplied for each exception throws t{//Because generics and type erase throw (T) e;}    
        • Suppose that the method is placed in class Block, if Block.<runtimeexception>throwas (t) is called; The compiler will assume that T is an unchecked exception
        • PublicAbstractClassblock{PublicAbstractvoid Body ()ThrowsException;PublicThread Tothread () {return new Thread () { Span style= "color: #0000ff;" >public void run () {try {body ();} catch (Throwable t) {block.<runtimeexception>< Span style= "color: #000000;" >throwas (t); } } }; } @SuppressWarnings ("Unchecked" ) public static <t extends throwable> void Throwas ( Throwable e) throws t{ Throw (T) e;}           
        • Write a test class again.
        • Publicclass test{public Span style= "color: #0000ff;" >static void main (string[] args) {new Block () {public throws exception{ // No Ixenos file will produce ioexception,checked exception! Scanner in = new Scanner (new File ("Ixenos" )); while 
            • After the thread is started, the Throwas method captures all checked exceptions to the thread's Run method, and "processes" the unchecked Exception (in fact, only cheats the compiler) after the throw;
            • What's the point ? Normally, because the run () method is declared to not throw any checked exceptions, all checked exceptions must be caught and "wrapped" into an unchecked exception; meaning : When we do this, we do not have to capture all and wrap to the unchecked exception. We just throw an exception and "trick" the compiler.

Notice the conflict after erasing

    • There is a principle in the Java Generics specification: "To support erase conversions, you need to force a restriction on a generic class or a type variable T to be a subclass of two interface types at the same time , which are different parameterization of the unified interface "
      • Note: A non-generic class can implement the same interface at the same time, no generics, good handling
      • Implements Comparable<calender>{...} //ERROR  
        • Here the Ggcalender class will implement both Comparable<calender> and Comparable<ggcalender>, which are different parameterization of the same interface

Generic constraints and restrictions for Java

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.