泛型的高級運用,代碼重構必須要瞭解的技巧 前言 泛型的運用 場景二 場景三 總結

前言

泛型相信大家都不陌生,經常都會用到,像在一些集合類啊,一些開源框架啊,這種東西隨處可見,如果不能好好理解的話,看起源碼來也會增加了一點兒複雜度。

泛型的好處,擴展性強,低耦合業務內容,大幅度的減少重複代碼。

本篇文章,基於對泛型有一定了解,想更進一步運用的朋友。

泛型的運用

場景一

當我們寫了一個採用泛型的類,但是怎麼獲取到這個類上的泛型呢,直接 run 一段簡短的代碼看下。

/**
 * @author: wangqp
 * @create: 2020-11-18 15:02
 */
public class GenericApply<T,U> {

    public T apply(T t){
        return t;
    }

    public List<String> getGenericClassName(){
        List<String> ret = new ArrayList<>();
        Type genericSuperclass = getClass().getGenericSuperclass();
        Type[] actualTypeArguments = ((ParameterizedType) genericSuperclass).getActualTypeArguments();
        Stream.of(actualTypeArguments).forEach(type -> {
            ret.add(((Class)type).getName());
        });
        return ret;
    }

    public static void main(String[] args) {
        //  匿名的子類實現
        GenericApply genericApply = new GenericApply<Integer,Boolean>() {};
        System.out.println(genericApply.getGenericClassName());
    }
}
1234567891011121314151617181920212223242526

運行結果:

可以看到,GenericApply 這類上有兩個泛型參數,使用上面的方法後,咱們可以得到全面的泛型全類名。

注意:類上加泛型,最好使用在抽象類上或者接口類上。

場景二

泛型在抽象類和接口類上,我們怎麼運用獲取呢,展示下代碼。

這裏劃分了三個類,接口類、抽象類、實現類。

接口類

public interface IGeneric<I> {
    void process(I i);
}
123

抽象類

public abstract class AbstractGeneric<T> {

    // 當前泛型真實類型的Class
    private final Class<T> modelClass;

    public AbstractGeneric(){
        ParameterizedType parameterizedType = (ParameterizedType)this.getClass().getGenericSuperclass();
        modelClass = (Class<T>)parameterizedType.getActualTypeArguments()[0];
    }

    public Class<T> getGeneric(){
        return modelClass;
    }
}
1234567891011121314

實現類

public class GenericImpl extends AbstractGeneric<String> implements IGeneric<Boolean>{

    @Override
    public void process(Boolean param) {

    }

    public static void main(String[] args) {
        GenericImpl generic = new GenericImpl();
        System.out.println("抽象類上的泛型全類名 "+generic.getGeneric().getName()+"\n");

        Type[] genericInterfaces = generic.getClass().getGenericInterfaces();
        for (Type genericInterface : genericInterfaces) {
            Type[] actualTypeArguments = ((ParameterizedType) genericInterface).getActualTypeArguments();

            Stream.of(actualTypeArguments).forEach(type -> {
                System.out.println("接口類上的泛型全類名 "+((Class) type).getName());
            });
        }
    }
}
123456789101112131415161718192021

運行結果:

看到運行結果可以打印出抽象類上後者接口上的泛型,這種應該是咱們經常使用的方式。

場景三

還有種更高級的用法,這種用法是和註解一起用的。用於標記泛型。

咱們在上面可以看到泛型參數返回來的是個數組,也就是咱們必須知道這個類的泛型位置,才能找到數組上對應位置的泛型類。
有沒有一種辦法,我不通過數組下標呢。其實是有的,咱們可以通過註解的方式,標定我們的泛型類,不是很複雜,咱們可以一起來看下。直接簡單看下代碼。

註解類

//相當於標註,找到註解爲 value 值的 泛型類
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_PARAMETER,ElementType.TYPE_USE})
public @interface MyAxis {
    String value() default "";
}
123456

接口泛型類

//相當於標註,找到註解爲 value 值的 泛型類
public interface IMultiParamInterface<@MyAxis(FIRST) T extends String,@MyAxis(SECONDE) U extends Integer> {
    String FIRST="FIRST";
    String SECONDE="SECONDE";

    void process();
}
1234567

實現類

public class MultiParamsImpl implements IMultiParamInterface<String,Integer>{

    @Override
    public void process() {
        System.out.println("MultiParamsImpl is invoke process");
    }

    //測試
    public static void main(String[] args) {
        Class<MultiParamsImpl> multiParamsClass = MultiParamsImpl.class;
        //得到這個接口上的 所有泛型
        Map<TypeVariable<?>, Type> typeArguments = TypeUtils.getTypeArguments(multiParamsClass, IMultiParamInterface.class);
        for (Map.Entry<TypeVariable<?>, Type> typeVariableTypeEntry : typeArguments.entrySet()) {
            TypeVariable<?> key = typeVariableTypeEntry.getKey();
            MyAxis annotation = AnnotationUtils.getAnnotation(key, MyAxis.class);
            Type value = typeVariableTypeEntry.getValue();
            System.out.println("名稱爲:"+ annotation.value() +" 泛型類全限定名: "+value.getTypeName());
        }
    }
}
1234567891011121314151617181920

上面就是接口上有多個泛型,分別被標註爲不同的名字,便於正確獲取到想要的泛型類型。

運行結果:

總結

上面列舉了泛型與抽象列,接口,註解在一起的多種運用和獲取方式。泛型還是很重要的,希望我上面列舉的對朋友們有點兒幫助。另外幫忙多點點讚唄,有什麼疑問,大家可以評論區指出。

作者:vicoqi

鏈接:https://blog.csdn.net/vicoqi/article/details/109773834?utm_medium=distribute.pc_category.none-task-blog-hot-7.nonecase&depth_1-utm_source=distribute.pc_category.none-task-blog-hot-7.nonecase

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章