Home  >  Article  >  Java  >  Java--Generics

Java--Generics

巴扎黑
巴扎黑Original
2017-06-27 09:13:571864browse

Type parameters

Use when defining a generic class or declaring a variable of a generic class Angle brackets to specify formal type parameters. The relationship between formal type parameters and actual type parameters is similar to the relationship between formal method parameters and actual method parameters, except that type parameters represent types rather than values.

Named type parameters

The recommended naming convention is to use uppercase, single-letter names for type parameters. This differs from the C++ convention (see Appendix A: Comparison with C++ templates), and reflects the assumption that most generic classes will have a small number of type parameters. For common generic patterns, the recommended name is:

K - key, such as a mapped key.
V —— Value, such as the contents of List and Set, or the value in Map.
E ——Exception class.
T —— Generic.

方法签名由方法名称和一个参数列表(方法的参数的顺序和类型)组成。

##1. Why use generics

1. There is no limit to the elements that can be put in. Putting in two different objects may cause exceptions.

2. Throw the object into the collection. The collection loses the state information of the object. The collection only knows that it holds Object, so after taking out the collection elements, it usually Force conversion is also required

2. What are generics

Java's parameterized types are called generics, which allow the program to specify the type of collection elements when creating a collection

3. Generic diamond Syntax

only needs to be followed by a pair of diamond brackets, no generics are required

4. Create a custom class with a generic declaration. When defining a constructor for the class, the constructor name should still be the original class name. Do not add a generic declaration.

5. Derive a subclass from a generic class. When inheriting, you must pass in the actual parameters for the parent class

public class A extends Applef7e83be87db5cd2d9a8a0b8117b38cd4{}

##All methods in it that override the parent class become the corresponding type

You can also pass in no actual parameters

##public class A extends Apple{}

Treat as Object type

6. There is no generic class

No matter what the actual type parameters of generics are, they always have the same class at runtime. No matter which type of actual parameter is passed into the generic type parameter, ( lies in the purpose of the concept of generics in Java, which causes it to only act in the code compilation phase. During the compilation process, After the generic result is correctly verified, the generic related information will be erased. That is to say, the successfully compiled class file does not contain any generic information and will not enter the runtime phase##. #.) For Java, they are still treated as the same class and occupy a memory space in the memory. Therefore, types are not allowed to be used in the declaration and initialization of static methods, static initialization blocks or static variables. Formal parameters

Explanation:

Static variables are shared by all instances of a generic class. For a class declared as MyClass8742468051c85b06f0a0af9e3e506b5c, the method to access the static variables in it is still MyClass.myStaticVar. Regardless of whether the objects are created through new MyClassf7e83be87db5cd2d9a8a0b8117b38cd4 or new MyClassc0f559cc8d56b43654fcbe4aa9df7b4a, they all share a static variable. Assume that type parameters are allowed as types of static variables. Then consider the following situation:

MyClassf7e83be87db5cd2d9a8a0b8117b38cd4 class1 = new MyClassf7e83be87db5cd2d9a8a0b8117b38cd4();

MyClassc0f559cc8d56b43654fcbe4aa9df7b4a class2 = new MyClassc0f559cc8d56b43654fcbe4aa9df7b4a();

class1.myStaticVar = "hello";

class2.myStaticVar = 5;

Due to the type erasure of the generic system Except (type erasure). myStaticVar is restored to the Object type, and then when class1.myStaticVar= "hello"; is called, the compiler performs forced type conversion, that is, myStaticVar = (String)"hello"; and then when the class2.myStaticVar statement is called, the compiler continues to perform forced type conversion. , myStaticVar = (Integer)Integer.valueOf(5); At this time, myStaticVar is of type String. Of course, this statement will throw a ClassCastException at runtime, so there is a type safety issue. Therefore, the generic system does not allow static variables of a class to use type parameters as variable types.

# Generic classes will not actually be generated in the system, so the generic class cannot be used after the instanceod operator because it does not exist at all!

7. Type wildcard

Note that, If Foo is a subtype of Bar and G is a class or interface with a generic declaration, G4ee996100bf04ab273e687539c860625 is not a subtype of Gad40e550a33cb99ea30eede96e03e60e.

##Assuming that Lista87fdacec66f0909fc0757c19f2d2b1d can be logically regarded as the parent class of Listf7e83be87db5cd2d9a8a0b8117b38cd4, then a.test(list) will not have an error message , then the question arises, what type is the data when it is retrieved through the getData() method? Integer? Float? Or Object? And due to the uncontrollable order in the programming process, type judgment and forced type conversion must be performed when necessary. Obviously, this contradicts the concept of generics. Therefore, Logically Lista87fdacec66f0909fc0757c19f2d2b1d cannot be regarded as the parent class of Listf7e83be87db5cd2d9a8a0b8117b38cd4

In order to represent the parent class of various generic collections, you can use type wildcards. The type wildcard is a Question mark, it can match any type:

Type wildcard is generally used? instead of specific type actual parameters. Note, here are type actual parameters, not type parameters! And List6b3d0130bba23ae47fe2b8e8cddf0195 is logically the parent class of all Listc1ce73470528dace954681dc986cdbf2 such as Listc0f559cc8d56b43654fcbe4aa9df7b4a, List9e1dffd95b2420e71a54038daf9f7c1a... etc. From this, we can still define generic methods to fulfill such requirements.

No matter what the real type of the list is, it contains Object

Note: with wildcards only means It is the parent class of various generic collections and cannot add elements to it

We do not know the type of elements in the c collection and cannot add objects to it

7.1 Set the upper limit of wildcards

##Because Listc13078eef089064b7e80988f58350b9c is not a subtype of List5c58ee79afe736c10ab537fb5aaf549d, a compilation error occurred

This can be recycled Use restricted generic wildcards

7.2 Setting upper limits on type parameters

8. Generic method

define class, The interface does not use type parameters. When defining the method, I want to define

independent generic static method at the same time without considering multi-threading. point, it will only be initialized and called once, there will be no overlapping initialization and incorrect calls, and there will be no situation like reading dirty data in the database, so there will be no code errors in forced type conversion.

The formal parameters defined in the method declaration can only be used in this method.

Unlike classes and interfaces, generics in methods do not need to show the actual type parameters passed in

You must not let the compiler confuse what type you pass in

For example, test

If you pass in a String type or an Object type, the compiler does not know what type your T is.

Can it be changed to 3d1e4407ce2609b4cda8049c3f8dbafb a, Collection8742468051c85b06f0a0af9e3e506b5c b>

Generic method

(in type parameter one section) You have seen that you can make a class generic by adding a list of formal type parameters to its definition. Methods can also be genericized, regardless of whether the class in which they are defined is generic or not.

# Generic classes enforce type constraints across multiple method signatures. In Listd94943c0b4933ad8cac500132f64757f, the type parameter V appears in the signatures of methods such as get(), add(), contains(), and so on. When you create a variable of type Mapb56561a2c0bc639cf0044c0859afb88f, you declare a type constraint between methods. The value you pass to add() will be of the same type as the value returned by get().

#Similarly, you declare a generic method generally because you want to declare a type constraint between multiple parameters of the method. For example, the ifThenElse() method in the following code will return either the second or third argument, depending on the Boolean value of its first argument:

public 8742468051c85b06f0a0af9e3e506b5c T ifThenElse(boolean b, T first, T second) {
return b ? first : second;
}

Note that you can call ifThenElse() without explicitly telling the compiler what you want for T value. The compiler doesn't have to be told explicitly what values ​​T will have; it just knows that the values ​​must all be the same. The compiler allows you to call the following code because the compiler can use type inference to deduce that the String substituted for T satisfies all type constraints:

##String s = ifThenElse(b, "a", "b");

##Similarly, you can call:

Integer i = ifThenElse(b, new Integer(1), new Integer(2));

However, compile The following code is not allowed by the compiler because no type would satisfy the required type constraints:

##String s = ifThenElse(b, "pi", new Float( 3.14));

Why did you choose to use a generic method instead of adding type T to the class definition? There are (at least) two cases where this should be done:

#When a generic method is static, class type parameters cannot be used in this case.

When a type constraint on T is truly local to a method, it means that there is no use of the same type T in another method signature of the same class constraint. The signature of a closed type can be simplified by making the type parameters of a generic method local to the method.


Restricted types

Generic methods in the previous screen In the example, the type parameter V is an unconstrained or unrestricted type. Sometimes it is necessary to specify additional constraints on type parameters when the type parameters have not been fully specified.

Consider the example Matrix class, which uses a type parameter V, which is bounded by the Number class:

public class Matrixae0232c3244c2cc6df973fad5b129c33 { ... }

The compiler allows you to create Matrixc0f559cc8d56b43654fcbe4aa9df7b4a or Matrix8dd2730a9d553ba0024e58b921fa6ad1 type, but if you try to define a variable of type Matrixf7e83be87db5cd2d9a8a0b8117b38cd4, an error will occur. Type parameter V is evaluated to be bounded by Number . In the absence of type restrictions, type parameters are assumed to be restricted by Object. This is why the example in the previous screen, Generic Methods, allows List.get() to return Object when called on a List6b3d0130bba23ae47fe2b8e8cddf0195, even if the compiler doesn't know the type of the type parameter V.

9. The difference between generic methods and type wildcards

If a method If the type of formal parameter (a) or the type of the return value depends on the type of another formal parameter (b), then the type declaration of formal parameter (b) should not use wildcards, and only the type parameter can be considered to be declared in the method signature. , that is, a generic method.

What I understand is that the type wildcard does not need to add or modify the elements in the collection, and it is attached to others rather than others attached to him. Use

Type wildcards can be used to define the type of formal parameters in method signatures or to define the types of variables. Type parameters in generic methods must be explicitly declared in the corresponding method.

10. Wiping and conversion

When assigning an object with generic information to another When adding a variable without generic information, all type information between angle brackets is thrown away.

##When assigning li to List, the compiler will Erase the former's generic information, that is, lose the type information of the elements in the list collection.

Java also allows the list object to be directly assigned to a List30690cee1a11d5dfbdced93b89f678ee variable, so the program can be compiled and passed, but

"unchecked conversion" is issued (the logical parent class directly assigned to the subclass), but the list variable actually refers to the listc0f559cc8d56b43654fcbe4aa9df7b4a collection, so when trying to take out the elements in the collection as a String type object, a run will be triggered Exception

11. Generics and arrays

Java generics have a very important design principle---if a piece of code does not raise an "unconverted exception" warning when compiling, the program will not cause a ClassCastException exception. For this reason, The type of all array elements cannot contain type variables or type parameters, unless it is an unlimited type wildcard, but the element type can be declared to contain an array of type variables or type parameters

Assuming it can pass, no warning will be caused, but an exception will be thrown

Change Into the following format:

The first line will have an "unchecked conversion" warning, and the last line will also throw an exception

Create unlimited wildcards Generic array

#Compilation will not issue any warnings, but an exception will be thrown at runtime because the program needs to force the first collection element of the first array element of lsa Convert to String type, so the program should use the instanceof operator to ensure its data type

Similarly, creating an array object whose element type is a type variable will also cause compilation Error

8742468051c85b06f0a0af9e3e506b5c T[] makeArray(Collection8742468051c85b06f0a0af9e3e506b5c coll)

{ return new T[cool.size()]

}

The type variable does not exist at runtime and the compiler cannot determine what the actual type is

The above is the detailed content of Java--Generics. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn