Java-泛型及其通配符

1.类的泛型

class Person<T> {
    //泛型作为一个参数(使用的时候有些像类,但不是类)
    private String name;
    private int age;
    private T t;

    public Person(String name, int age, T t) {
        this.name = name;
        this.age = age;
        this.t = t;
    }

    //有自己的get,set
    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

测试类中使用: 建议实例化时候指明泛型的类型

    public static void main(String[] args) {
        //1.初始化时,没有指明类的泛型类型,则认为是Ojbect类(这样和不加泛型直接定义Object一样了)

        Person person = new Person("Jack", 21, "Runner");
        person.setT(12);
        //2.建议在实例化的时候指明泛型的类型
        Person<String> person1 = new Person<>("Jack", 12, "Runner");
        //person1.setT(12);//编译错误,只能添加String类型,类型更加安全了
    }

2.子类继承父类泛型情况

        1.class Student extends Person<String>{} 子类继承父类的时候,指明了泛型,子类实例化的时候不需要,指明泛型,(其实子类不是泛型类);

        2.class Student<T> extends Person<T>{} 子类继承父类的时候,没有指明泛型的类型,子类实例化的时候,泛型默认Object类,需要再次指明泛型

3.泛型类型不同的引用不能相互赋值

        ArrayList<Integer> list1 = null;

         ArrayList<String>list2 = null;

        list1 = list2;//编译错误

4.泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但是不等同Object;

    经验: 要使用泛型,一路使用,要不使用,一路都不要使用。 

 5.静态方法中不能使用类的泛型。

        类的泛型是随着对象创建指定的类型,而静态方法早于对象的创建

        public static void test( T t){//形参报错

                print(t);//报错

        }

6.异常类不能是泛型的 

7.泛型方法: 泛型方法中泛型参数,与类的泛型参数没有任何关系。

                       泛型方法与类是不是泛型类没有关系。 

举个栗子: 

 public <E> List<E> copyArraytoList(E[] arr) {
        ArrayList<E> list= new ArrayList<>();
        for (E e : arr) {
            list.add(e);
        }
        return list;
    }
    @Test
    public void testMethod(){
        Integer[] arr = new Integer[]{1, 3, 5, 3, 23, 54};
        List<Integer> list = copyArraytoList(arr);
        System.out.println(list);//[1, 3, 5, 3, 23, 54]
    }

8. 泛型方法可以是静态的static

public static <E> List<E> copyArraytoList(E[] arr) {}

         泛型方法的泛型参数是在调用的时候指定的,不论是类的调用还是对象的调用都是一样。

9.通配符
    9.1通配符,代表未知类型,代表不关心或无法确定实际操作的类型,一般与容器类配合使用。
    9.2<? extends T>,定义上限,期间只有阅读能力。这种方法表明参数化的类型可能是指定的类型或子类型。
    9.3<? super T>,下限定义,有阅读能力和部分写作能力,子类可以写入父类。这种方法表明参数化的类型可以是指定的类型,也可以是父类。 

 @Test
    public  void test1(){
        List<Object> list2 = null;
        List<Integer>list1 = null;
        //相当于把 list<?> 看作是父类
        List<?> list = null;
        list = list1;
        list = list2;       
    }

注意:List<?>list ; 不能往list添加元素,可以添加null。(不能写入数据)

        可以读取list中数据,读取的数据类型为Object。

public void print(List<?> list) {
        Iterator<?> iterator = list.iterator();
        while (iterator.hasNext()) {
            //Object 表示最高的父类,所以能用Object接收
            Object obj = iterator.next();
            System.out.println(obj);
        }
    }

举个栗子:

        G<? extends A>  可以看作是 G<A> 及其G<A>所有子类
        G<? super A>    可以看作是  G<A> 及其G<A>所有父类

   List<? extends Person>list =null;
        List<? super  Person> list1 = null;

        List<Object>list2 = null;
        List<Person> list3 = null;
        List<Student >list4 = null;

        list = list2;//报错
        list = list3;
        list = list4;

        list1 = list2;
        list1 = list3;
        list1 = list4;//报错

        G<? extends A>  可以看作是 G<A> 及其G<A>所有子类
        G<? super A>    可以看作是  G<A> 及其G<A>所有父类

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值