java generics Detailed + clever use of the source code of Ali fastjson

introduction

Speaking before Ali fastjson, talk about some of the basics under the generic generics and how to get in reflection, feel that they have mastered directly through the catalog view Skip to end

Generic class

As long as the definition of the generic class declaration class, directly after the class name plus <E>, the letter E can be any, may be a plurality, the plurality can be separated by commas. The following sample code

public class SelfList<E> {}
复制代码

The generic class of the actual type inference

So when determining the specific type E it? In fact, is specified in the new, when an object, look at the code below

public class SelfList<E> {

    public void add(E e) {
        if (e instanceof String) {
            System.out.println(" I am String");
        } else if (e instanceof Integer) {
            System.out.println("I am Integer");
        }
    }
    public static void main(String[] args) {
        //这里创建的时候指定了String
        SelfList<String> a = new SelfList<String>();
        a.add("123");
        //这里创建的时候指定了Integer
        SelfList<Integer> b = new SelfList<Integer>();
        b.add(123);
    }

}

复制代码

Generic Interface

Use the same generic interfaces and classes

public interface IndicatorTypeService<T> {}

//这里定义的时候指定具体类型为ProductSale,当然也可以这里没有指定具体类型   
public class ProductSaleServiceImpl implements IndicatorTypeService<ProductSale> {}
复制代码

Generic method

I think this is relatively rare, we concentrate on what I say, maybe a generic method you've always thought is false. Well, give a fake generic method for everyone to experience it, or the above code examples for easy reading I paste the code again

   //注意这是个假的泛型方法,不要以为有一个E就是泛型方法哦
    public void add(E e) {
        if (e instanceof String) {
            System.out.println(" I am String");
        } else if (e instanceof Integer) {
            System.out.println("I am Integer");
        }
    }
复制代码

The definition of a generic method

Well, the focus here, give a true generic method definition out

    public <T> T get(T t) {
        return t;
    }
复制代码
  1. Between the public and the return value of <T> generic method is a necessary condition, and the definition of the generic and class E is of the same name (typically set different names), and are independent between them.
  2. <T> may be a plurality, the plurality of separated by commas, such as column <T, V>
  3. The return value is not necessarily is T, it may be of any type, such as Long
  4. The method is not necessarily a parameter is T, may be of any type, such as Long. Usually just a generic method return type and parameters which have a defined generic (all types of concrete no significance)
    public <T> T get(T t) {
        return t;
    }
    public static void main(String[] args) {
        //这里创建的时候指定了String
        SelfList<String> a = new SelfList<String>();
        a.add("123");
        int num = a.get(123);
    }
复制代码

Generic methods actual generic inference

Then the generic method is how to determine the specific type of it? The main idea is to call the generic method parameter types and pass in the return type to determine the specific type of

  1. Generic variable occurs only once in the parameter list, determined according to the type of arguments for transmission of this method is invoked
    public <T>  T get1(T t) {
        if (t instanceof String) {
            System.out.println(" I am String");
        } else if (t instanceof Integer) {
            System.out.println("I am Integer");
        }
        return t;
    }

    public static void main(String[] args) {
        SelfList<String> a = new SelfList<String>();
        //这里调用的时候传进去的是int 类型,所以确定了他的类型是int
        int b=a.get1(123);
    }
复制代码

Output

I am Integer
复制代码
  1. When the parameter list of a plurality of parameters using the same type variable, the type of the return value of the variable is also used, the type of the return value to determine the final generic type by their common parent class
    public <T> T get2(T t, T t2) {
        if (t instanceof Float) {
            System.out.println(" I am String");
        } else if (t instanceof Integer) {
            System.out.println("I am Integer");
        } else if (t instanceof Number) {
            System.out.println("I am Number");

        }
        return t;
    }

    public static void main(String[] args) {
        SelfList<String> a = new SelfList<String>();
        //这里返回值类型必须是number 类型
        Number b = a.get2(123, 12.1);
    }
复制代码

Note that the above output will be

I am Integer
复制代码

Because according to the first rule, pass in what type is what type, but the type of the return value candidates need to be determined the second rule

Generics reflections

The above said are compiled before it can be determined generics. As we all know, time is running generic actually will be erased. But it's still available to us to get through reflection. First, I come to know the generic type of inheritance structure under java

Here is mainly about the use of the usual maximum of three classes, there are some other GenericArrayType like not talk about it, everyone pressing my analysis of this idea you can go to

Source ParameterizedType

public interface ParameterizedType extends Type {
    /**
     * 返回一个实际类型的数组
     * 比如对于ArrayList<T>,被实例化的时候ArrayList<String>,这里返回的就是String
     *
     */
    Type[] getActualTypeArguments();

    /**
     * 这里其实就是返回去掉泛型后的真实类型
     * 对于List<T> 这里返回就是List
     */
    Type getRawType();

    /**
     * 这里针对的是内部类的情况,返回的是他的外层的类的类型
     * 例如SelfHashMap  里面有一个Entry 内部类,也就是SelfHashMap.Entry<String,String>
     * 返回的就是SelfHashMap
     */
    Type getOwnerType();
}
复制代码

ParameterizedType verification test

Define an inner class class

public class SelfHashMap {

    public static class Entry<T, V extends Collection> {

    }

}
复制代码

Write a test class

public class ParameterizedTypeTest {

    public static void main(String[] args) {
        Class clazz = A.class;
        //注意这里是拿父类的泛型,jdk 没有提供本类的泛型
        Type type = clazz.getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            System.out.println(Arrays.toString(parameterizedType.getActualTypeArguments()));
            System.out.println(parameterizedType.getRawType());
            System.out.println(parameterizedType.getOwnerType());
        }




    }

    /**
     * 这里的泛型被是指定了为String 和List
     * getActualTypeArguments() 会输出 String 和List
     */
    public static class A extends SelfHashMap.Entry<String, List> {

    }

}
复制代码

Output

[class java.lang.String, interface java.util.List]
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap$Entry
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap
复制代码

Source TypeVariable

public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    /**
     * 这里返回的是泛型的上界类型数组,比如 <T, V extends Collection> 这里的上界类型就是Collection
    */
    Type[] getBounds();

    /**
     * 返回的是声明该泛型变量的类,接口,方法等
     * 列如 public static class Entry<T, V extends Collection> 返回的就是Entry
     */
    D getGenericDeclaration();

    /**
     * 这里返回的就是泛型定义的变量名称,比如 <T>  返回的就是T
     *
     */
    String getName();

    /**
     * 这里返回的就是AnnotatedType 数组,jdk1.8 才加进来,本文不分析,直接跳过
     */
     AnnotatedType[] getAnnotatedBounds();
}
复制代码

Write a test class

public class TypeVariableTest {

    public static void main(String[] args) {
        Class clazz = SelfHashMap.Entry.class;
        TypeVariable[] typeVariables = clazz.getTypeParameters();
        for (TypeVariable ty :typeVariables) {
            System.out.println(ty.getName());
            System.out.println(Arrays.toString(ty.getAnnotatedBounds()));
            System.out.println((Arrays.toString(ty.getBounds())));
            System.out.println(ty.getGenericDeclaration());
            System.out.println("============================");
        }

    }

}
复制代码

The results output

T
[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@3fee733d]
[class java.lang.Object]
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap$Entry
============================
V
[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@5acf9800]
[interface java.util.Collection]
class com.wizhuo.jdklearning.reflect.dto.SelfHashMap$Entry
复制代码

Ali fastjson clever use of generics

See the following code, a simple means is to obtain the string from Redis, then converted to the generic class designation. We can notice here created a TypeReference anonymous class is back with a note {}, it is an instance of an anonymous inner class (which is the focus of the focus, all the magic from here), instead of the class TypeReference examples

        List<ResourceEntity> resources =
            redisAdapter.get(BaseConstant.TENANT_CODE_SYSTEM, CacheKey.KEY_ALL_RESOURCE,
                new TypeReference<List<ResourceEntity>>() {
                });
复制代码

Snoop Source

Look at this point into the source code


    protected final Type type;
    /**
     *注意这里protected ,也就意味着我们创建的时候只能继承这个类成为他的子类,毕竟我们的类
     * 不可能和阿里巴巴的fastjson 在同一个包目录下
     *
     * 一般我们都是创建一个匿名内部类来成为他的子类,然后泛型中传进我们想要转化的最终泛型 
     * 例如上面的代码new TypeReference<List<ResourceEntity>>() {}  List<ResourceEntity> 是我们想要转化的类型
     *           
     * 
     */
    protected TypeReference(){
        //这里是获取父类的泛型,由于jdk 不支持获取自己的泛型,这里巧妙的通过继承这个类,变成获取父类的泛型来解决
        Type superClass = getClass().getGenericSuperclass();
        //这里返回泛型的实际类型,就是 List<ResourceEntity>
        type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }
复制代码

After reading two things

If you find this content you quite inspiring, I want to invite you to help me a little busy 2:

  1. Thumbs up, so that more people can see this content (collection point no praise, bullying -_-)
  2. No public concern "interview bat" from time to time to share knowledge of the original, the original is not easy, like him to support (which also offers brushes title applet oh).

Guess you like

Origin juejin.im/post/5de713fc51882512360d383f