On the type derivation of Java 8’s new feature generics

1. What is generics?

Before discussing type inference, we must review what is generic Generics is a new feature of Java se 1.5. The essence of generics is parameterized types, that is, the data type operated is specified as a parameter. The popular point will be "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 regard it as a convenient syntax, which can save you some operations on Java type casting:

The above code itself has been clearly expressed: @ r_ 20_ 2419 @ is a list containing apple objects. The get method returns an apple object instance. This process does not require type conversion. Without generics, the above code needs to be written as follows:

Of course, generics is not as simple as I described here, but this is not our protagonist today. Students who do not understand generics need to make up lessons ~ of course, the best reference is the official documents.

2. Problems caused by generics (before Java 7)

The biggest advantage of generics is that it provides program type safety and backward compatibility, but it also annoys developers. It is necessary to specify the type of generics every time. In this way, the display and designation not only feels a little lengthy, but most importantly, many programmers are not familiar with generics, so they can't give correct type parameters many times, Now the compiler can automatically infer the parameter types of generic types, which can reduce this situation and improve the readability of the code.

3. Improvement on type derivation of generics in Java 7

When using generic types in versions before Java 7, you need to add generic types on both sides when declaring and assigning values. For example:

Many people must have been as puzzled as me: didn't I declare the parameter type in the variable declaration? Why is it necessary to write the displayed when the object is initialized? This is where many people make complaints about generics when they first appeared. However, it is gratifying that while Java is making progress, those designers are also constantly improving the java compiler to make it more intelligent and humanized. Here is our protagonist today: type push down Um Instead of pushing down, it is type derivation, that is, type information. When writing the above code, you can happily omit the parameter type during object instantiation, which becomes like this:

In this statement, the compiler will automatically infer the generic type when instantiating HashMap according to the generic type at the time of variable declaration. Again, you must pay attention to the "< >" after the new HashMap. Only adding this "< >" means automatic type inference, otherwise it is a non generic HashMap, and an unchecked conversion warning will be given when compiling the source code with the compiler. This pair of angle brackets "< >" is called "diamond" in the official document.

But, At this time, the type derivation is not complete (or even a semi-finished product), because the type inference when creating generic instances in Java se 7 is limited: type inference can only be used if the parameterized type of the constructor is significantly declared in the context, otherwise it cannot be used. For example, the following example cannot be compiled correctly in Java 7 (but now it can be compiled in Java 8, because the type of generic type is automatically inferred according to the method parameters):

4. Re evolution in Java 8

In the latest official JAVA document, 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 refers to the ability of the compiler to determine the required parameter types according to the methods you call and the corresponding declarations. An example is also given in the official document:

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

In previous Java versions, the above example needs to be written if it can be compiled:

The detailed reasons for this can be found in Bruce Eckel's Java programming idea You can see the chapter on generics in the (Fourth Edition). Of course, this book is based on Java 6. This version does not have the concept of type derivation. Many people can clearly see the strength of type derivation in the latest version. It is not limited to the declaration and instantiation of generic classes, but extends to methods with generic parameters.

4.1 type inference and generic methods

For the type derivation and generic methods in the new version, the document also provides a slightly more complex example. I post it here. The principle is the same as the above serializable example, so I won't repeat it. If you want to consolidate, you can take another look:

The output of the above code is:

By the way, generic methods add@R_20_2419 @The key point is that in the new Java version, you no longer need to display the type description in the method call, like this:

The compiler can pass in add@R_20_2419 @The parameter in automatically infers that the parameter type is integer

4.2 type inference and generic constructors of generic and non generic classes

Um This may be a better sentence in English: type infrastructure and generic constructors of generic and non generic classes

In fact, generic constructors are not the patent of generic classes. Non generic classes can also have their own generic constructors. Take a look at this example:

Suppose you instantiate MyClass as follows:

OK, here we clearly point out that the generic parameter type X of MyClass is integer, and for the constructor, the compiler deduces that the formal parameter t is string according to the incoming string object (""). This has been implemented in java7. What improvements have been made in java8? After java8, we can write as follows for the instantiation of this generic class with generic constructor:

Yes, this pair of angle brackets (< >) is also called diamond in Jianghu, so our compiler can automatically deduce that the formal parameter x is integer and t is string. In fact, this is very similar to our example of map < string, string > at the beginning, except for the generalization of multiple constructors.

It should be noted that type derivation can only be deduced according to the parameter type of the call, the target type (which will be discussed shortly) and the return type (if there is a return), but not according to some requirements later in the program.

4.3 target type

As mentioned earlier, the compiler can type derivation based on the target type. The target type of an expression refers to the correct data type required by the compiler according to the location of the expression. For example:

Here, list < string > is the target type, because what is needed here is list < string > and collections Emptylist() returns list < T >, so the compiler infers that t must be a string. This is OK in Java 7 and 8. However, in Java 7, it cannot be compiled normally in the following cases:

At this time, java7 will give this error prompt:

Reason: collections Emptylist() returns list < T >, where t needs a specific type, but the compiler gives t an object value because it cannot be inferred from the method declaration. Obviously, list < Object > cannot be transformed to list < string > So in the Java 7 version, you need to call this method as follows:

However, in java8, due to the introduction of the concept of target type, it is obvious that the compiler needs list < string > (that is, the target type here), so the compiler infers that t in the returned list < T > must be string, so processstringlist (collections. Emptylist()); This description is OK.

The use of target types has the most obvious advantage in lambda expressions.

summary

Well, the above are some personal opinions on type derivation in Java. In summary, more and more perfect type derivation is to complete some type conversion work that I take for granted, but these work are fully handed over to the compiler for automatic derivation rather than being explicitly specified by developers. I hope the content of this article can help you learn Java. If you have any questions, you can leave a message.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>