了解泛型

本文主要通过代码来展示

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 1.泛型方法&非泛型方法
 * 2.无限定符
 * 3.泛型上限&泛型下限
 * 4.特殊方法equals
 * 5.泛型擦除&利用反射擦除泛型
 * 6.泛型的参数类型
 * 7.静态常量或静态方法中的泛型
 * 8.泛型数组
 * 9.泛型与可变参数
 * @param <E>
 */
public class Generator<E> {
    /**
     * E的类型需要与声明类时的类型一致,这里不是泛型方法
     * @param element
     * @return
     */
    E next(E element){return null;}

    /**
     * E的类型可以与声明类时的类型不一致,这里是泛型方法
     * @param element
     * @param <E>
     * @return
     */
    <E> E upload(E element){return null;}

    /**
     * 当具体类型不确定的时候,这个通配符就是 ?,可以看成所有类型的父类型
     * @param element
     */
    void show(Generator<?> element){}

    /**
     * 方法内是被无限定符修饰的参数,它隐略的表达了一个意图,或者说可以是限定,那就是这个方法不需要关心List中的真实类型。因为它是未知的。
     * 所以只能使用List中无关类型的方法。
     *
     * <?>提供了只读的功能,也就是它删减了增加具体类型元素的能力,只保留与具体类型无关的功能。
     * 它不管装载在这个容器内的元素是什么类型,它只关心元素的数量、容器是否为空
     * @param list
     */
    public void showTest(List<?> list){
        //list.add(12); //报错
        //list.add("hello");// 报错

        Object o = list.get(0);
        int size = list.size();
    }

    /**
     * 泛型方法的基本介绍
     * @param tClass 传入的泛型实参
     * @return T 返回值为T类型
     * 说明:
     *     1)public 与 返回值中间<T>非常重要,可以理解为声明此方法为泛型方法。
     *     2)只有声明了<T>的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。
     *     3)<T>表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。
     *     4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。
     */
    <K> K left(Class<K> tClass){return null;}

    /**
     * 为泛型添加上边界,即传入的类型实参必须是指定类型的子类型
     * @param tClass
     */
    void rigth(Generator<? extends Number> tClass){}

    /**
     * 为泛型添加下边界,即传入的类型实参必须是指定类型的父类型
     * @param element
     */
    void load(Generator<? super E> element){}

    /**
     * 在泛型方法中添加上下边界限制的时候,必须在权限声明与返回值之间的<T>上添加上下边界,即在泛型声明的时候添加
     * @param element
     * @param <E>
     * @return
     */
    public <E extends Number> E down(E element){return null;}

    /**
     * 因为泛型擦除后该方法就会变成
     *  boolean equals(Object obj);
     *  和Object.equal()冲突
     */
    //boolean equals(E element){} //这是错误的

    /**
     * 泛型类中的静态方法和静态变量不可以使用泛型类所声明的泛型类型参数
     * 因为泛型类中的泛型参数的实例化是在定义对象的时候指定的,而静态变量和静态方法不需要使用对象来调用。
     * 对象都没有创建,如何确定这个泛型参数是何种类型,所以当然是错误的
     * @param element
     * @return
     */
    //public static E getInstance(E element){return null;} // 这是错误的

    /**
     * 使用方法时传入指定的类型:这个是泛型方法
     * 因为这是一个泛型方法,在泛型方法中使用的T是自己在方法中定义的T,而不是泛型类中的T
     * @param element
     * @param <E>
     * @return
     */
    public static <E> E getEntity(E element){return null;}//这是正确的

    /**
     * 泛型类型不能使用基本类型
     * @param element
     */
    //public void addEntity(Generator<int> element){ } // 这是错误的


    /**
     * 泛型只在编译阶段起作用,运行时会把泛型擦除,所以会输出true
     * @param args
     */
    /*public static void main(String[] args){
        Generator<String> entity1 = new Generator<>();
        Generator<Integer> entity2 = new Generator<>();
        System.out.println(entity1.getClass() == entity2.getClass());//true
    }*/

    /**
     * 泛型数组问题
     * @param args
     */
    /*public static void main(String[] args) {
        *//**
         * 原因还是类型擦除带来的影响
         *//*
        // List<String>[] list1 = new ArrayList<String>[10]; //这是错误的

        *//**
         * 借助于无限定通配符却可以,前面讲过 ?代表未知类型,所以它涉及的操作都基本上与类型无关,
         * 因此 jvm 不需要针对它对类型作判断,因此它能编译通过,但是,只提供了数组中的元素因为通配符原因,它只能读,不能写。
         * 比如,上面的 v 这个局部变量,它只能进行 get() 操作,不能进行 add() 操作
         *//*
        List<?>[] list2 = new ArrayList<?>[10];//这是正确的
        list2[1] = new ArrayList<String>();
        List<?> list3 = list2[1];
    }*/

    /**
     * 利用泛型擦除向集合中添加元素
     * @param args
     * @throws ClassNotFoundException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    /*public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        //list.add(1); // 这是错误的,类型检查不通过

        // 通过反射擦除类型,添加到集合中
        Class<?> clazz = Class.forName("java.util.ArrayList");
        Method addMethod = clazz.getMethod("add", Object.class);
        addMethod.invoke(list,1);
        System.out.println(list); // [a,b,1]
    }*/

    /**
     * 泛型与可变参数
     * @param args
     * @param <E>
     */
    public static <E> void printArray(E... args){
        for(E e : args){
            System.out.println(e);
        }
    }

    public static void main(String[] args) {
        printArray(1,2,3,"a","b","c");
    }

}

demo2.实现泛型接口的泛型类

public interface GeneratorA<E> {
    E getEntity();
}

/**
 * public class GeneratorAImpl implements GeneratorA<E> 这样会报错
 * 未传入泛型实参时,与泛型类的定义相同,在声明类的时候,需将泛型的声明也一起加到类中
 */
public class GeneratorAImpl<E> implements GeneratorA<E>{
    @Override
    public E getEntity() {
        return null;
    }
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值