Generic two-generic and array

Source: Internet
Author: User
Tags reflection wrapper
What is the difference between an array and a generic container

To differentiate between arrays and the functionality of a generic container, there are three concepts to understand: covariance (covariance), contravariance (contravariance), and extraneous (invariant).

If Class A is a subclass of class B, it is recorded as a a≦b. With a transform f (), if:

       When A≦b, there is f (a) ≦f (B), then the transformation F () has covariance, and

when A≦b, there is f (B) ≦f (a), then the transformation F () is said to have inverse degeneration

, and if neither of the above is true, the transformation F () is irrelevant.

In Java, arrays have covariance, and generics are irrelevant, and the sample code is as follows:

object[] array = new STRING[10];
Compilation error arraylist<object> list=new arraylist<string> ();

These two lines of code, the array of normal compilation through, and generics throw a compile-time error, the application of the concept proposed before the Code analysis, know:

1, String≦object

2, the transformation of the array can be expressed as F (A) =a[], through the previous example, you can deduce:

f (String) = string[] and f (Object) = object[];

4, through the code verification, string[]≦object[] is established, this shows that the array has covariance.

Also know:

5. The transformation of the ArrayList generic type can be expressed as f (A) = Arraylist<a>, and deduced:

f (String) = Arraylist<string> and f (Object) = arraylist&  lt;object>;

6, through the code to verify the,arraylist<string>≦arraylist<object> is not established, it can be seen that the generic type with invariance

Finally, we conclude that the array is covariant and the generics are invariant.

So, in order for generics to have covariance and contravariance, Java introduces the concept of bounded generics (see 3.1.2 section content).

In addition to covariance, arrays are also representational, and generics are not.

What is representational (reified, also can be called materialization, materialization).

In the Java language Specification, the definition of the representational type is specified:

Types that are fully available at run time are called refiable types, and this distinction is made because some types are erased during compilation and not all types are available at run time.

It includes:

1. Non-generic class declaration, interface type declaration;

2. All generic parameter types are unbounded wildcard characters (only '? ') modification) of the generic parameter class;

3, the original type;

4, basic data type;

5. The element type is an array with the image type;

6. Nested classes (internal classes, anonymous inner classes, etc., such as java.util.HashMap.Entry), and each class in the nesting process is representational.

Arrays can know exactly what type they belong to, both at compile time and at run time. However, generics lose some type information at compile time, and at runtime it is treated as object.

This involves the knowledge of type erasure, which is explained in detail later. At the moment, just know that Java generics are finally treated as an upper bound (the concept will be described later).

Extension: The array has covariance, is a Java flaw, because very few places need to use the covariance of the array, or even, the use of the covariance of the array will cause difficult to check the run-time exception, see the following code:

object[] array = new STRING[10];

Array[0] = 1;

Obviously, this throws an exception at run time: java.lang.ArrayStoreException.

Given that there are so many differences in Java, arrays and generics are not mixed. See the following code:

list<string>[] Genericlistarray = new arraylist<string>[10];

t[] Genericarray = new t[];

They all throw cannot create a generic array errors at compile time. This is because the array requirement type is refied, and generics are not.

In other words, the array must know the type of its internal element clearly, and it will keep the type information, and the information will be used for type checking when the element is added, while the type of the generic type is indeterminate. So, at the compiler level, this problem is eliminated. This is clearly stated in the Java language specification:

If the element type of an array were not reifiable,the virtual machine could not perform the store check described in the preceding paragraph. This is why creation of arrays of non-reifiable types is forbidden. One may declare variables of array types whose element type are not reifiable, but any attempt to assign them a value would Give rise to a unchecked warning.

If the element type of the array is not representational, the virtual machine will not be able to apply the storage checks described in the previous chapters. This is why it is forbidden to create (instantiate) an array that is not a visual image. You can define (declare) that an element type is a unchecked array type, but any operation that assigns a value to it will produce a warning.

Storage check: This involves the basics of array, which you can refer to in the Java language Specification or reference 5.1.1ArrayList related chapters

This has to say, is Java in the generic design of a little flaw, why Java generics design there are so many flaws. Is it really not good enough for the Java language? The content will be answered in the 3.3-section generic history.

Generic Usage Recommendations

Generics play an important role in Java development and design, and it is especially important to use generics correctly and efficiently. Here's how to deepen your understanding of generics by introducing two suggestions for using generics:

1. A generic type can only be a class type, not a basic data type, and should use its corresponding wrapper class if you want to use the base data type as a generic. For example, if you expect to store a shape variable in a list, because int is a basic type, you can't use List<int>, you should use INT's wrapper class Integer, so the correct way to use it is list<integer>.

Of course, generics do not support basic data types, and attempts to use basic data types as generics must be translated into wrapper classes, a flaw in Java generic design.

2, when using to the collection, try to use a generic set to replace the Non-generic collection. Generally speaking, the software development period and maintenance period of time accounted for, also conforms to the 28 law, maintenance period can exceed the development period of several times. Using a generic collection at least, on the IDE tools, is type-determined, which can improve the readability of your code and avoid some serious bugs at compile time.

3, do not use common class names (especially string this belongs to Java.lang) as the generic name, will cause the compiler can not distinguish between the Open class and generics, and will not throw an exception.

Generic Erase

Before learning generic erasure, it is clear that the Java generics do not exist at run time. That's why some people say that Java has no real generics.

Generic Erase (Type erase), it means that when the compiler processes a class \ Interface \ method with a generic definition, it erases all the generic type information in the byte-code instruction set, erases the generic, and retains only the original type of the generic in the byte code (raw type).

The original type is the type that erases the generic information, in Java, it must be a reference type (a non-basic data type) and, in general, it corresponds to the upper bounds of the definition of the generic type.

For example, the original generic for T in:<t> is object,<t extends string> corresponding to the original type is String. generic information is erased at compile time

How to prove that generics will be erased. A test code is provided here:

Class Typeerasuresample<t> {public

T v1;

Public T v2;

Public String v3;

}

 

/**

 * Generic Erase example/public

class Generic3_2 {public

static void Main (string[] args) throws Exception {

T ypeerasuresample<string> type = new Typeerasuresample<string> ();

TYPE.V1 = "String value";

 

The value of the Reflection setting V2 is the integer

Field v2 = TypeErasureSample.class.getDeclaredField ("v2");

V2.set (type, 1);

 

For (Field F:typeerasuresample.class.getdeclaredfields ()) {

System.out.println (f.getname () + ":" + F.gettype ());

}

 * * Here will throw Java.lang.ClassCastException:java.lang.Integer cannot be cast

 * to java.lang.String * *

System.out.println (TYPE.V2);

}

The result of the program running is:

V1:class Java.lang.Object

V2:class Java.lang.Object

V3:class java.lang.String

Exception in thread "main" Java.lang.ClassCastException:java.lang.Integer cannot is cast to java.lang.String

At Capter3.generic.Generic3_2.main (generic3_2.java:29)

The types of V1 and v2 are specified as generic T, but they are found by reflection to be essentially object, and V3 is defined as String, and the first two pairs, proving that there is no error in the reflection itself.

The code throws a type conversion exception in the process of outputting TYPE.V2, which illustrates two things:

1, for the V2 set integer number has been successful (you can write a reflection to verify);

2, the compiler in the construction of bytecode, must do a similar (String) Type.v2 forced conversion, in this regard, you can compile the validation (Jd-gui tool), the results are as follows:

public class Generic3_2

{public

  static void Main (string[] args) throws Exception

  {

    typeerasuresample Type = new Typeerasuresample ();

    TYPE.V1 = "String value";

 

    Field v2 = TypeErasureSample.class.getDeclaredField ("v2");

    V2.set (Type, integer.valueof (1));

 

    For (Field F:typeerasuresample.class.getdeclaredfields ()) {

      System.out.println (f.getname () + ":" + F.gettype ()); c9/>}

 

    System.out.println ((String) type.v2);

  }

As you can see, if the compiler thinks that type.v2 is necessary to be declared as a string, it will be forced to convert (string). You can test:

Object o = type.v2;

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.