In detail Java8 the type derivation of the generic type of new characteristics _java

Source: Internet
Author: User
Tags addall java se

1. What is a generic type?

Before you discuss type inference (types inference), you must review what generics (Generic) is. Generics are a new feature of Java SE 1.5, and generics are essentially parameterized types, meaning that the data type being manipulated is specified as a parameter. The popular point is "variable of type". This type of variable can be used in the creation of classes, interfaces, and methods. The easiest way to understand Java generics is to think of it as a handy syntax that saves you casting from some of the actions on Java type conversions ():

list<apple> box = new arraylist<apple> (); Box.add (new Apple ());
Apple Apple =box.get (0);

The above code itself has made it clear that box is an apple-loaded object List . getmethod returns an instance of an Apple object that does not require a type conversion. Without generics, the code above needs to be written like this:

Apple Apple = (apple) box.get (0);

Of course, generics are not as simple as I described here, but this is not our protagonist today, for generics are not very clear to the students need to catch up ~ Of course, the best reference or official documents.

2. Generics pose problems (before Java 7)

The greatest advantage of generics is that it provides type safety for the program and can be backwards compatible. But there is also a problem with developers, that is, every time you define a generic type, so that the display specifies not only feel a bit verbose, most of the programmers are unfamiliar with generics, so many times can not give the correct type parameters, It is now possible to automatically infer the parameter types of generics through the compiler, reducing the situation and improving the readability of the code.

3. Improvements to generic type derivation in Java 7

Using a generic type in a previous version of Java 7, you need to add a generic type to both sides when declaring and assigning a value. Let's say this:

 
 

Many people would have been as puzzled as I was: did I not declare the parameter type in the variable declaration? Why do I have to display the object when it is initialized? This is where the generics were spit out by a lot of people when they first appeared. However, it is gratifying that Java in the progress of the same time, those designers are constantly improving the Java compiler, let it become more intelligent and humane. Here, is our protagonist today: the type of ... Amount of ... is not to pull down, is the type of derivation, that is, the kind of inference, this buddy's appearance, and then write the above code, you can be very happy to omit the object instantiation of the parameter type, it becomes this way:

map<string,integer> map = new hashmap<> ();

In this statement, the compiler automatically infers the generic type when instantiated, based on the generic type at the time of the variable declaration HashMap . Again, be sure to pay attention to the new HashMap "<>" that follows, and only add this "<>" to indicate that it is automatic type inference, otherwise it is non-generic and HashMap gives a warning prompt when compiling source code using the compiler (unchecked Conversion warning). This pair of angle brackets "<>" is called "Diamond" in the official document.

However, this time the type deduction does not complete (even a semi-finished), because type inference is limited when a generic instance is created in Java SE 7: Only the parameterized type of the constructor is declared prominently in the context, it is not possible to use type inference. For example: The following example is not compiled correctly in Java 7 (but now it can be compiled in JAVA8 because the type of the generic is automatically inferred based on the method parameters):

list<string> list = new arraylist<> ();
List.add ("A");//Because AddAll expect to get collection<? Extends string> type parameters, so the following statement cannot pass
List.addall (new arraylist<> ());

4. Re-evolution in the JAVA8

In the latest Java official documentation, we can see the definition of type derivation:

Type inference is a Java compiler ' s ability to look at each of the invocation and corresponding declaration to determine T He type argument (or arguments) this make the invocation applicable. The inference algorithm determines the types of the arguments and, if available, the type is being Assigne D, or returned. Finally, the inference algorithm tries to find the most specific type is the arguments.

In short, type inference refers to the ability of the compiler to determine the type of argument required according to the method you call and the corresponding declaration. And an example is also given in the official document to explain:

Static <T> T pick (t A1, T A2) {return a2;}
Serializable s = pick ("D", New Arraylist<string> ());

Here, the compiler is able to deduce the pick type of the second parameter in the incoming method Serializable .

In previous Java versions, the above example would need to be written by compiling the words:

Serializable s = This.<serializable>pick ("D", New Arraylist<string> ());

The detailed reasons for this can be seen in the generic chapter of Bruce Eckel's Java Programming Idea (fourth edition), which is based on JAVA6, and this version has no type to deduce the concept. See here, a lot of people have obviously been able to see the strength of the type derivation in the latest version. is not limited to the declaration and instantiation process of a generic class, but extends to a method with generic parameters.

4.1 Type derivation and generic methods (type inference and Generic Methods)

On the new version of type derivation and generic methods, the document also gives a slightly more complex example, I posted here, the principle and the example above are Serializable no longer repeat, want to consolidate the can look again:

public class Boxdemo {public

 static <U> void Addbox (U, 
 java.util.list<box<u>> boxes) {
 box<u> box = new box<> ();
 Box.set (u);
 Boxes.add (box);

 public static <U> void Outputboxes (java.util.list<box<u>> boxes) {
 int counter = 0;
 for (box<u> box:boxes) {
 U boxcontents = Box.get ();
 System.out.println ("Box #" + Counter + "contains [" +
  boxcontents.tostring () + "]");
 counter++
 }
 }

 public static void Main (string[] args) {
 java.util.arraylist<box<integer>> listofintegerboxes =
 new Java.util.arraylist<> ();
 Boxdemo.<integer>addbox (integer.valueof), listofintegerboxes);
 Boxdemo.addbox (integer.valueof), listofintegerboxes);
 Boxdemo.addbox (integer.valueof), listofintegerboxes);
 Boxdemo.outputboxes (listofintegerboxes);
 }

The above code output is:

Box #0 contains [a] box
#1 contains [30]
box #2 contains []

To mention, the generic approach is focused on the addBox type description that you do not need to display in the method call in the new Java version, like this:

Boxdemo.<integer>addbox (integer.valueof), listofintegerboxes);

The compiler is able to addBox automatically infer the parameter type from the arguments passed in Integer .

4.2 Type derivation generic constructor (type inference and Generic constructors of Generic and Non-generic Classes) with generic and Non-generic classes

Amount of ... This may be a better way of English punctuation: Type Inference and Generic constructors of Generic and Non-generic Classes

In fact, generic constructors are not proprietary to generic classes, and Non-generic classes can have their own generic constructors, and look at this example:

Class Myclass<x> {
 <T> MyClass (T t) {
 //...
 }
}}

If you make the following instantiation of the MyClass class:

New Myclass<integer> ("")

OK, here we show that MyClass's generic parameter type X is Integer , and for the constructor, the compiler derives the form parameter based on the incoming String object (""), which has String been implemented in the JAVA7 version, and what improvements have been made in Java8? After Java8, we can write this to instantiate a generic class that has a generic constructor:

myclass<integer> myObject = new Myclass<> ("");

Yes, or this pair of angle brackets (<>), Lake Person Diamond, so that our compiler can automatically deduce the form parameter x is Integer , T is String . This actually Map<String,String> looks like the example we started with, but it's just a generic form of a constructor.

It should be noted that type inference can only be inferred based on the type of argument invoked, the target type (which is immediately mentioned) and the return type (if there is a return), but not on some of the requirements behind the program.

4.3 Target type

As mentioned earlier, the compiler is able to type derivation based on the target type. The target type of an expression refers to the correct data type that the compiler needs to be based on where the expression appears. Like this example:

Static <T> list<t> emptylist ();
list<string> Listone = Collections.emptylist ();

Here,list<string> is the target type, because what is needed here is the List<String> Collections.emptyList() return List<T> , so here the compiler infers that T must be String . This is OK in Java 7 and 8. In Java 7, however, you cannot compile correctly in the following scenario:

void Processstringlist (list<string> stringlist) {
 //process stringlist
}

processstringlist ( Collections.emptylist ());

At this point, Java7 will give this error message:

List<object> cannot be converted to list<string>

Reason: Collections.emptyList()  The return is List<T> that the t here needs a specific type, but since the desired is not inferred from the method declaration, the String compiler gives T a Object value, obviously, that List<Object> cannot be transformed into List<String>. So in the JAVA7 version you need to call this method:

Processstringlist (Collections.<string>emptylist ());

However, in Java8, because of the introduction of the concept of the target type, it is obvious here that the compiler needs (that is, List<String> the target type here), so the compiler infers that the List<T> T in return must be String , so processStringList(Collections.emptyList()); this description is OK.

The use of target types is most obvious in lambda expressions.

Summarize

Well, here are some personal insights into the type derivation in Java, and in conclusion, the more and more perfect type derivation is the completion of some of the type conversions that would have been taken for granted, except that the work was all over the place to the compiler to automatically deduce rather than let the developer display the designation. Hope that the content of this article for you to learn Java can help, if you have questions can be exchanged message.

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.