Constraints and limitations of Java generics

Source: Internet
Author: User
Tags comparable throwable

Constraints and limitations of Java generics

@author Ixenos

    • 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, only tests whether a is a pair of any type, You see the compiler error warning  if  (a instanceof  pair<t>) // pair  <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:
      • New // ERROR
        • by compiler type is erased, the type of table is pair[], which can be a covariant group of object[], for example://Note that this pair is static type, not a generic parameter, so pair[]
        •  object[] Objarray =
               Table; 
        • The
        • array remembers his element type pair, if you attempt to store other types of elements , an exception is thrown ( array store check ), for example:
        •  objarray[0] = "Hello"; //
               error--component type is Pair  
        • however, for generic type pair<string>, type erasure invalidates this different class-checking mechanism, for example:
        •  objarray[0] = new  pair<employee> (); 
          The
          • array store only checks the type of erasure, and because the Java language Design array can be covariant , it can be checked through the array store by compiling
          • , but it will still result in a type error, so creating a parameter is not allowed Array of type
          • Note that variables that declare type pair<string>[] are legal, but they cannot be created (directly initialized with new PAIR<STRING>[10]
      • indirect implementation of a generic array: The generic array wrapper, such as the ArrayList class, maintains an object array and then indirectly implements the generic array by qualifying the type with the import and export method set, get, and the cast array type, for example: 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) {    tryreturn  New pair<>(Cl.newinstance (), cl.newinstance ());}     Catch return NULL ; }} // This method can be called in the following ways: Pair<string> p = Pair.makepair (String.  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 to go. At this point, we have to use reflection, call Array.newinstance:

          •  import java.lang.reflect.*; ....  public  static  <t extends Comparable> t[] Minmax (T ... a) {t[] mm  = (t[]) array.newinstance (A.getclass (). Getcomponenttype (), 2   

             

            • "API Document description" PUBLIC&NBSP;CLASS<?>&NBSP; 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 object[] Array
                 Public object[] ToArray () {        return  arrays.copyof (elementdata, size);    }
            • copyOf (t[] Original,int newlength)
              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 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, but my contents:            return(t[]) arrays.copyof (elementdata, size, A.getclass ()),//a.getclass () runtime type of the run-time destination array System.arraycop Y (Elementdata,0, A, 0, size); if(A.length >size) A[size]=NULL; returnA; }
              • "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
      •  Public class Singleton<t>{    privatestatic//ERRORpublic      static//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
        • Therefore, it is forbidden to use static and static methods with type variables in a generic class

  • 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
      •  Public Static extends void doWork (class<t> T) {    try{            do work         }  Catch//  ERROR            Logger.global.info (...)        }}

    • However, it is permissible to use type variables in the exception specification:  
      •  public  static  <t "extends  throwable> void  doWork (T t)  Throws  T {//  at this point you can throws T  try  do   work}  catch  (Throwable realcause) {//
                   Capture to a specific instance   T.initcause (realcause);  throw  t; //  at this time the concrete instance is thrown, so the throw T and throws T are OK!   
        • 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  publicstaticextendsvoidthrows  t{  //Because generics and type erase , can pass any checked exception, for example RuntimeException class exception     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
            •  Public Abstract classblock{ Public Abstract voidBody ()throwsException;  PublicThread Tothread () {return NewThread () { Public voidrun () {Try{body (); }Catch(Throwable t) {Block.<RuntimeException>Throwas (t);    }                        }                    }; } @SuppressWarnings ("Unchecked")     Public Static<textendsThrowable>voidThrowas (Throwable e)throwst{Throw(T) e; }}
            • Write a test class again.
            •  Public classtest{ Public Static voidMain (string[] args) {NewBlock () { Public voidBody ()throwsexception{//non-existent Ixenos file will produce ioexception,checked exception! Scanner in =NewScanner (NewFile ("Ixenos"));  while(In.hasnext ()) System.out.println (In.next ());    }}.tothread (). Start (); }}    
            • 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; You don't have to capture all of it and wrap it into the unchecked exception, we just throw the 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
        • class Implements Comparable<calender>{...} class extends Implements // ERROR

          • Here the Ggcalender class will implement both Comparable<calender> and Comparable<ggcalender>, which are different parameterization of the same interface

Constraints and limitations of Java generics

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.