Java 8 new features: Generic Type derivation; java New Features

Source: Internet
Author: User
Tags addall

Java 8 new features: Generic Type derivation; java New Features

1. What is generic?

Before discussing type inference, you must review what is Generic ). generics are new features of Java SE 1.5. The nature of generics is parameterized, that is, the Data Type operated is specified as a parameter. Popular points are "type variables ". This type of variable can be used to create classes, interfaces, and methods. The simplest way to Understand Java generics is to look at it as a convenient syntax, which can save some Java type conversion (casting) operations:

List<Apple> box = new ArrayList<Apple>();box.add(new Apple());
Apple apple =box.get(0);

The code above has clearly expressed that box is a List containing Apple objects. The get method returns an Apple object instance, which does not require type conversion. No generics. The code above needs to be written as follows:

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

Of course, generics are not as simple as I described here, but they are not the main character of today. Students who are not quite familiar with generics need to make up their courses ~ Of course, the best reference is the official document.

2. Problems Caused by generics (before Java 7)

The biggest advantage of generics is that it provides program type security and can be backward compatible, but it also makes the developer uncomfortable, that is, the generic type should be written in every definition, in this way, specifying parameters is not only lengthy, but many programmers are not familiar with generics. Therefore, they are often unable to provide correct type parameters. Now, the compiler can automatically infer the type of generic parameters, this can reduce the situation and improve code readability.

3. Improvements in generic type derivation in Java 7

To use generic types in versions earlier than Java 7, you must add them to both sides when declaring and assigning values. For example:

Map<String,Integer> map = new HashMap<String,Integer>(); 

Many people must have been like me at the beginning, so they are puzzled: Have I declared the parameter type in the variable declaration? Why should I write the display during object initialization? This is where many people talk about generics at the beginning. However, while java is improving, those designers are constantly improving the java compiler to make it more intelligent and user-friendly. Here is the main character of today: Type push... amount... if it is not a type deduction, that is, type inference, the appearance of this buddy can happily omit the parameter type during Object Instantiation when writing the above Code, this is what it looks like:

Map<String,Integer> map = new HashMap<>();

In this statement, the compiler automatically deduce the generic type when instantiating HashMap based on the generic type During Variable declaration. Note that "<>" after the new HashMap is added. Only the "<>" is used to indicate automatic type inference. Otherwise, it is a non-generic type HashMap, when the compiler is used to compile the source code, a warning message (unchecked conversion warning) is displayed ). This pair of angle brackets "<>" officially referred to as "diamond ".

However, the type derivation at this time is not complete (or even a semi-finished product), because there are restrictions on the type inference when creating a generic instance in Java SE 7: type inference can be used only when the parameterized type of the constructor is explicitly declared in the context; otherwise, no. For example, the following example cannot be correctly compiled in java 7 (but can be compiled in java 8 now, because the generic type is automatically inferred based on method parameters ):

List <String> list = new ArrayList <> (); list. add ("A"); // The Collection is expected due to addAll <? Extends String> type parameter. Therefore, the following statement cannot pass list. addAll (new ArrayList <> ());

4. redevelopment in Java 8

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

Type inference is a Java compiler's ability to look at each method invocation and corresponding declaration to determine the type argument (or arguments) that make the invocation applicable. The inference algorithm determines the types of the arguments and, if available, the type that the result is being assigned, or returned. Finally, the inference algorithm tries to find the most specific type that works with all of the arguments.

In short, type derivation means that the compiler can determine the required parameter types based on the methods you call and the corresponding declarations. The official document also provides an example to illustrate:

static <T> T pick(T a1, T a2) { return a2; }Serializable s = pick("d", new ArrayList<String>());

Here, the compiler can deduce that the type of the second parameter passed into the pick method is Serializable.

In the previous java version, if the above example needs to be compiled, it should be written as follows:

Serializable s = this.<Serializable>pick("d", new ArrayList<String>());

The detailed reason for writing this can be found in the general type chapter of Bruce Eckel's java programming ideology (Fourth Edition). Of course, this book is based on java 6, this version does not have the concept of Type derivation. Many people can see the strength of Type derivation in the latest version. It is not limited to the declaration and instantiation of generic classes, but to methods with generic parameters.

4.1 Type Inference and Generic Methods (Type Inference and Generic Methods)

With regard to the type derivation and generic methods in the new version, the document also provides a slightly more complex example. I will post it here. The principle is the same as the above Serializable example and I will not repeat it here, to consolidate it, let's take a look:

public class BoxDemo {  public static <U> void addBox(U 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(10), listOfIntegerBoxes);    BoxDemo.addBox(Integer.valueOf(20), listOfIntegerBoxes);    BoxDemo.addBox(Integer.valueOf(30), listOfIntegerBoxes);    BoxDemo.outputBoxes(listOfIntegerBoxes);  }}

The above code output is:

Box #0 contains [10]Box #1 contains [20]Box #2 contains [30]

The focus of the generic method addBox is that in the new java version, you do not need to describe the type displayed in the method call, as shown in the following code:

BoxDemo.<Integer>addBox(Integer.valueOf(10), listOfIntegerBoxes);

The compiler can automatically infer from the input parameters in addBox that the parameter type is Integer.

4.2 Type derivation and Generic and Non-Generic Constructors (Type Inference and Generic Constructors of Generic and Non-Generic Classes)

Amount... this may be a better sentence in English: Type Inference and Generic Constructors of Generic and Non-Generic Classes

In fact, the generic constructor is not a patent product of the generic class. Non-generic constructor can also have its own generic constructor. Let's take a look at this example:

class MyClass<X> {  <T> MyClass(T t) {    // ...  }}

Suppose the following instantiation is made for the MyClass class:

new MyClass<Integer>("")

OK. Here we show that the generic parameter Type X of MyClass is Integer. For constructors, the compiler pushes and exports the form parameter T according to the passed String object, this has been implemented in Java 7. What improvements have been made in Java 8? After Java 8, we can write the following for the instantiation of this generic class with a generic constructor:

MyClass<Integer> myObject = new MyClass<>("");

Yes, this pair of angle brackets (<>) is called diamond, so that our compiler can automatically export the form parameter X as Integer and T as String. In fact, this is very similar to the example of Map <String, String> at the beginning, but it only has a wildcard constructor.

It should be noted that type derivation can only be performed based on the called parameter type, target type (which will be discussed immediately), and return type (if any, but cannot be deduced according to some requirements behind the program.

4.3 Target Type (Target Type)

As mentioned above, the compiler can perform type derivation based on the target type. The target type of an expression refers to the correct data type that the compiler needs based on the position where the expression appears. For example:

static <T> List<T> emptyList();List<String> listOne = Collections.emptyList();

Here, List <String> is the target type, because List <String> and Collections are required. emptyList () returns List <T>, so the compiler infer that T must be a String. This is OK in both Java 7 and 8. However, in java 7, compilation fails in the following cases:

void processStringList(List<String> stringList) {    // process stringList}processStringList(Collections.emptyList());

At this time, Java 7 will prompt this error:

//List<Object> cannot be converted to List<String>

Cause: Collections. emptyList () returns the List <T>. Here, T requires a specific type, but it cannot be inferred from the method declaration that the required String is required, therefore, the compiler gives T an Object value. Obviously, List <Object> cannot be transformed to List <String>. therefore, in Java 7, you need to call this method as follows:

processStringList(Collections.<String>emptyList());

However, in Java 8, due to the introduction of the concept of the Target Type, here, it is obvious that the compiler needs List <String> (that is, the Target Type here ), therefore, the compiler inferred that T in the returned List <T> must be String, so processStringList (Collections. emptyList (); this description is OK.

The use of the target type has the most obvious advantages in Lambda expressions. I will sort out the relevant content slowly.

 

Well, the above are some people's opinions on type derivation in java. To sum up, the more and more perfect type derivation is to complete some type conversion work that would have taken it for granted, it's just that all of this work is handed over to the compiler for automatic derivation, rather than letting developers explicitly specify it.

 

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.