Java generic TEKV? Detailed explanation

 

JAVA generic wildcard T, E, K, V difference, T and Class<T>, Class<?> difference

 

1. First explain the concept of generics

Generics is a new feature of Java SE 1.5. The essence of generics is a parameterized type, which means that the data type to be manipulated is specified as a parameter. This parameter type can be used in the creation of classes, interfaces, and methods, which are called generic classes , generic interfaces, and generic methods, respectively. The advantage of introducing generics in the Java language is that it is safe and simple.
Before Java SE 1.5, in the absence of generics, the "arbitraryization" of parameters was achieved through a reference to the type Object. The disadvantage of "arbitraryization" is that explicit coercion is required , and this The conversion is performed under the condition that the developer can predict the actual parameter type. In the case of a forced type conversion error, the compiler may not prompt an error, and an exception occurs only at runtime, which is a security risk. The benefit of generics is that type safety
is checked at compile time , and all casts are automatic and implicit to improve code reuse.

The above content is excerpted from Baidu Encyclopedia

For example: The
Box class is defined as a generic class

public class Box<T> {
    private T object;

    public void set(T object) { this.object = object; }
    public T get() { return object; }
}

Create a Box object without generic parameters, and find that you need to cast it when you get the object

Box box2 = new Box();
box2.set(new Apple());
Apple apple = (Apple) box2.get();

Create a Box object with generic parameters, no need to cast when getting the object

Box<Apple> box = new Box<Apple>();
box.set(new Apple());
Apple apple = box.get();

To sum up, the advantage of generics is that it
eliminates the need for forced conversion, can check type safety at compile time, and can be used in classes, methods, and interfaces.

But when we define generic classes, generic methods, and generic interfaces, we often encounter many different wildcards T, E, K, V, etc. What do these wildcards mean? keep looking down

2. Let's talk about the difference between generic wildcards T, E, K, V

These are all wildcards of java generics. At the beginning, I saw so many wildcards, and I was dizzy. There is no difference between these two, but it is just an agreed code, that is to say

Using uppercase letters A, B, C, D...

  • ? Represents an indeterminate java type
  • T (type) represents a specific java type
  • KV (key value) respectively represents the Key Value in the java key value
  • E (element) stands for Element

Take a chestnut:

public class Test<T> {    
  public List<T> list = new ArrayList<T>();   
  public static void main(String[] args) {
        Test<String> test = new Test<String>();
        test.list.add("hello");
        System.out.println(test.list);
    }}

and

public class Test<A> {    
  public List<A> list = new ArrayList<A>();   
  public static void main(String[] args) {
        Test<String> test = new Test<String>();
        test.list.add("hello");
        System.out.println(test.list);
    }}

Replacing T with A has no difference in execution effect, but we have agreed that T represents type, so it is better to follow the agreed specification, which increases the readability of the code.

If you want to define multiple generic parameters, such as two generic parameters,
a typical chestnut is the key and value generics of Map, we can also define such a

public interface Mymap<K, V> {
    public K getKey();
    public V getValue();
}

public class MymapImpl<K, V> implements Mymap<K, V> {

    private K key;
    private V value;

    public MymapImpl(K key, V value) {
    this.key = key;
    this.value = value;
    }

    public K getKey()    { return key; }
    public V getValue() { return value; }
}

You can pass in any type and create an instance without converting the type.

Mymap<String, Integer> mp1= new MymapImpl<String, Integer>("Even", 8);
Mymap<String, String>  mp2= new MymapImpl<String, String>("hello", "world");
Mymap<Integer, Integer> mp3= new MymapImpl<Integer, Integer>(888, 888);

If you want to define more than two, three or more generic parameters you can use T1, T2, ..., Tn, like this

public class Test<T1,T2,T3> {
   public void print(T1 t1,T2 t2,T3 t3){
        System.out.println(t1.getClass());
        System.out.println(t2.getClass());
        System.out.println(t3.getClass());
    }
}

3. Let’s talk about the difference between T, Class<T>, and Class<?>

T is a specific class, such as String, List, Map... etc. These are all specific classes. It is better to understand what
a Class is. Class is also a class, but Class is stored above String, List, Map... a class of class information, a bit abstract, let's look at it step by step.

How to get the Class class, there are three ways:
1. Call the getClass() method of the Object class to get the Class object, which is also the most common method to generate the Class object.
E.g:

List list = null;
Class clazz = list.getClass();

2. 使用Class类的中静态forName()方法获得与字符串对应的Class对象。 
例如:

Class clazz = Class.forName("com.lyang.demo.fanxing.People");

3.获取Class类型对象的第三个方法非常简单。如果T是一个Java类型,那么T.class就代表了匹配的类对象。

Class clazz = List.class;

那么问题来了?Class类是创建出来了,但是Class<T>和Class<?>适用于什么时候呢???

使用Class<T>和Class<?>多发生在反射场景下,先看看如果我们不使用泛型,反射创建一个类是什么样的。

People people = (People) Class.forName("com.lyang.demo.fanxing.People").newInstance();

看到了么,需要强转,如果反射的类型不是People类,就会报
java.lang.ClassCastException错误。

使用Class<T>泛型后,不用强转了

public class Test {
    public static <T> T createInstance(Class<T> clazz) throws IllegalAccessException, InstantiationException {
        return clazz.newInstance();
    }

    public static void main(String[] args)  throws IllegalAccessException, InstantiationException  {
            Fruit fruit= createInstance(Fruit .class);
            People people= createInstance(People.class);
    }
}

那Class<T>和Class<?>有什么区别呢?
Class<T>在实例化的时候,T要替换成具体类
Class<?>它是个通配泛型,?可以代表任何类型,主要用于声明时的限制情况
例如可以声明一个

public Class<?> clazz;

但是你不能声明一个

public Class<T> clazz;

因为T需要指定类型
所以当,不知道定声明什么类型的Class的时候可以定义一个Class<?>,Class<?>可以用于参数类型定义,方法返回值定义等。

以上所有示例的代码我已经提交到了github,有兴趣的同学可以去看看https://github.com/qwertyanglu/FanxingDemo

个人的一些理解,如果有不对的地方,欢迎各位前辈给出宝贵指导,在此先行谢过。

 

转自:http://www.jianshu.com/p/95f349258afb

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326266591&siteId=291194637