[Turn] T wildcard chat -JAVA Generics, E, K, V ,?

Original: https: //juejin.im/post/5d5789d26fb9a06ad0056bd9

 

Foreword

Java generics (generics) is a new feature introduced in JDK 5, generics provide compile-time type safety detection mechanism, this mechanism allows developers to detect illegal type at compile time.

Generic nature of the parameter type, data type that is being operated is specified as a parameter.

The benefits brought by generics

In the absence of generic case, the parameters achieved by reference to Object type "arbitrary" and "arbitrary" of the disadvantages of explicit do is cast, and this conversion is required developer the case of the actual parameter types can predict performed. For mandatory conversion error, the compiler may not prompt an error, it appears abnormal at run time, which is itself a security risk.

Then the generic benefit is able to check at compile time type safety, and all the cast are automatic and implicit.

public class GlmapperGeneric<T> { private T t; public void set(T t) { this.t = t; } public T get() { return t; } public static void main(String[] args) { // do nothing } /** * 不指定类型 */ public void noSpecifyType(){ GlmapperGeneric glmapperGeneric = new GlmapperGeneric(); glmapperGeneric.set("test"); // 需要强制类型转换 String test = (String) glmapperGeneric.get(); System.out.println(test); } /** * 指定类型 */ public void specifyType(){ GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric(); glmapperGeneric.set("test"); // 不需要强制类型转换 String test = glmapperGeneric.get(); System.out.println(test); } } 复制代码

specifyType method of the above code is omitted from cast, at compile time type safety check, it can be used in classes, methods, interfaces.

Generics wildcards

We define a generic class, generic methods, when generic interface often run into a lot of different wildcards, such as T, E, K, V, etc., these are the wild card and what does that mean?

Common T, E, K, V ,?

These are essentially a wildcard, nothing different, just something a convention when coding. For example, in the above code T, we can replace any letter between AZ can be, and will not affect the normal operation of the program, but if replaced by other letters instead of T, on the readability may be weaker. Typically, T, E, K, V ,? It is this agreement:

  • ? Represent undefined type java
  • T (type) is represented by a specific type java
  • KV (key value) represent the key Key Value java
  • E (element) on behalf of Element

? Unbounded wildcard

Start with a small example looks, the original  here  .

I have a parent class Animal and several sub-categories, such as dogs, cats, etc., and now I need a list of animals, my first thought was like this:

List<Animal> listAnimals
复制代码

But the boss's idea is really this:

List<? extends Animal> listAnimals
复制代码

Why use a wildcard rather than a simple generic it? Wildcards In fact, when you declare a local variable is meaningless, but when you declare a method as a parameter, it is very important.

static int countLegs (List<? extends Animal > animals ) { int retVal = 0; for ( Animal animal : animals ) { retVal += animal.countLegs(); } return retVal; } static int countLegs1 (List< Animal > animals ){ int retVal = 0; for ( Animal animal : animals ) { retVal += animal.countLegs(); } return retVal; } public static void main(String[] args) { List<Dog> dogs = new ArrayList<>(); // 不会报错 countLegs( dogs ); // 报错 countLegs1(dogs); } 复制代码

When you call countLegs1, it will be rosy, suggesting the following error message:

 

 

So, for uncertain or do not care about the type of operation to be practical, you can use an unrestricted wildcard (angle brackets in a question mark, that is <?>) Indicates that you can hold any type. Like countLegs approach, defining the last, but do not care about what specific type, so for all subclasses of Animal incoming can support, and does not complain. And countLegs1 can not.

The upper bound wildcard <? Extends E>

Last: The extends keyword statement, represents the parameterized type may be specified by type or subtype of class.

Represents the generic use extends the argument must be a subclass of E or E in a type parameter, this has two advantages:

  • If the incoming type is not a subclass of E or E, the compiler unsuccessful
  • Generics can use E method, or else have to turn into a strong E to use
private <K extends A, E extends B> E test(K arg1, E arg2){
    E result = arg2;
    arg2.compareTo(arg1);
    //..... return result; } 复制代码

Type parameter list if there are a plurality of types of parameters ceiling, separated by commas

Lower bound wildcard <? Super E>

Lower bound: declared by super, a parameter indicating the type may be of the type specified, or a supertype of this type until Object

Use super generic parameters indicates that the parent must be in the E or E type parameter.

private <T> void test(List<? super T> dst, List<T> src){ for (T t : src) { dst.add(t); } } public static void main(String[] args) { List<Dog> dogs = new ArrayList<>(); List<Animal> animals = new ArrayList<>(); new Test3().test(animals,dogs); } // Dog 是 Animal 的子类 class Dog extends Animal { } 复制代码

Type dst "not less than" src type, where the "Greater than" refers to a range of larger than dst indicates the src, dst so pretend to be a container can be installed src.

? And the difference between T

 

 

? And T have said the type of uncertainty, the difference is that we can operate on the T, but? No, this example is as follows:

// 可以
T t = operate();

// 不可以
? car = operate();
复制代码

Brief summary follows:

T is a certain type, and is typically used to define the generic class of the generic method,? Type is an uncertain, generally for a generic method and calling code parameter, a generic definition of classes and methods can not be used.

1 difference: to ensure the consistency of generic parameters by T

// 通过 T 来 确保 泛型参数的一致性
public <T extends Number> void
test(List<T> dest, List<T> src) //通配符是 不确定的,所以这个方法不能保证两个 List 具有相同的元素类型 public void test(List<? extends Number> dest, List<? extends Number> src) 复制代码

Like the following code, agreed that T Number of subclasses can be, but is declared when the String, so the error will be rosy.

 

 

List can not guarantee that two elements have the same type of situation

GlmapperGeneric<String> glmapperGeneric = new GlmapperGeneric<>();
List<String> dest = new ArrayList<>();
List<Number> src = new ArrayList<>();
glmapperGeneric.testNon(dest,src);
复制代码

The above code is not an error in the compiler, but when internal testNon method proceeds to operation (such as assignment), and for dest src, it would still require conversion.

2 differences: type multiple parameters may be defined not Wildcard

 

 

Symbol set & using multiple boundaries (Multi Bounds), T must be a generic type designated subtype consensus MultiLimitInterfaceB MultiLimitInterfaceA and at this time variable t is defined to have all the attributes and methods. For wildcards, because it is not a determination of the type can not be defined for multiple.

Difference 3: Wildcards can be defined using the superclass and not a type parameter

Type parameter T defines only one type by:

T extends A
复制代码

? But wildcards for either limited:

? extends A
? super A
复制代码

Class<T>And Class<?>the difference

Introduced in front of? And the difference between T, then for, Class<T>and <Class<?>what difference does it make?
Class<T>withClass<?>

The most common scenario is used in the reflection, where the code used to transmit the period will be described next.

// 通过反射的方式生成  multiLimit 
// 对象,这里比较明显的是,我们需要使用强制类型转换
MultiLimit multiLimit = (MultiLimit)
Class.forName("com.glmapper.bridge.boot.generic.MultiLimit").newInstance();
复制代码

For the above code at runtime, if the type is not reflected MultiLimit class, then it must be reported java.lang.ClassCastException error.

In this case, you can use the following code in place, so that at compile time to be able to directly check the types of problems:

 

 

Class<T>In the example of the time, T to be replaced with concrete classes. Class<?>It is a generic wildcard,? I can represent any type, so the limiting case is mainly used for the declaration. For example, we can do it states:

// 可以
public Class<?> clazz;
// 不可以,因为 T 需要指定类型
public Class<T> clazzT;
复制代码

So when you do not know what type of Class definite statement can define a Class <?>.

 

 

If you would like that public Class<T> clazzT;this is the case, we must let the current class also designated T,

public class Test3<T> { public Class<?> clazz; // 不会报错 public Class<T> clazzT; 复制代码

summary

本文零碎整理了下 JAVA 泛型中的一些点,不是很全,仅供参考。如果文中有不当的地方,欢迎指正。



Guess you like

Origin www.cnblogs.com/zdd-java/p/11653783.html