Day 16 (泛型)

本文详细介绍了Java中的泛型概念,包括如何在集合中使用泛型,自定义泛型类以及泛型方法的实现。同时,讨论了泛型类的子类继承情况,并举例说明了泛型方法的静态与非静态使用。此外,还讲解了通配符的使用,包括无限制和有限制条件的通配符在实际操作中的应用。
摘要由CSDN通过智能技术生成

 

目录

一、概念

二、自定义泛型类

三、泛型类

四、通配符


一、概念

/**
 * 在实例化集合类时,可以指明具体的泛型类型
 * 泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,使用包装类
 * 如果实例化没有使用泛型,默认类型为java.lang.Object类型
*/
    @Test
    public void test(){
        //在集合中使用泛型:ArrayList
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(12);
        list.add(1);
        list.add(2);
        list.add(0);

        //遍历方式一:采用foreach
        for (Integer score : list) {
            System.out.println(score);
        }
        //遍历方式二:采用Iterator
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()){
            Integer stuScore = iterator.next();
            System.out.println(stuScore);
        }
    }
         * 集合的输出利用Iterator接口完成;Map没有提供直接的Iterator接口
         * 使用Collection保存数据,直接保存所有对象
         * 使用Map保存数据时,所保存的key和value自动包装成Map.Entry接口对象
         *
         * Map利用Iterator:
         *      1、利用entrySet()方法将Map中的数据转换为Set接口实例;
         *      2、使用Set中的迭代iterator()方法
         *      3、每一次迭代都是取出Map.Entry接口实例,在创建该接口实例,调用getKey()                         
         *       getValue()方法获取相应的key-value值
//HashMap中使用泛型
    @Test
    public void test1(){
        //直接指定key-value的类型
        HashMap<String, Integer> map = new HashMap<>();
        map.put("aa",100);
        map.put("bb",900);
        map.put("cc",200);
        map.put("dd",300);
        map.put("ee",400);
        
        Set<Map.Entry<String, Integer>> set = map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> e = iterator.next();
            System.out.println(e.getKey() + "==" + e.getValue());
        }
    }

二、自定义泛型类

父类为泛型类

//泛型类
class Order<T> {
    String name;
    int Id;

    //类的内部结构可以使用类的泛型
    T orderT;

    public Order(){}

    public Order(String name, int Id, T orderT) {
        this.name = name;
        this.Id = Id;
        this.orderT = orderT;
    }

    public T getOrderT() {
        return orderT;
    }

    public void setOrderT(T orderT) {
        this.orderT = orderT;
    }

    @Override
    public String toString() {
        return "GenericClass{" +
                "name='" + name + '\'' +
                ", Id=" + Id +
                ", orderT=" + orderT +
                '}';
    }
}

 子类继承泛型类:

//subOrder1是泛型类
class subOrder1<T> extends Order<T>{}

//subOrder继承Order  并指明泛型<Integer>   此时subOrder不是泛型类
class subOrder extends Order<Integer>{}
    //实例化 泛型类 时 指明为String类型
 Order<String> order1 = new Order<String>("marry",22,"aa");
        //子类在继承带泛型的父类时,已经指明了泛型,则在实例化时不需要指明了
        subOrder subOrder = new subOrder();
        subOrder.setOrderT(123);

        //在继承时为指明类型 则实例化需要指明类型
        subOrder1<String> subOrder1 = new subOrder1<>();
        subOrder1.setOrderT("string类型");

子类继承泛型类的情况: 

class Father<T1,T2>{}
//子类不保留父类的泛型
    //(1)没有类型,擦除  
class son1 extends Father{}
    //(2)具体类型  
class son2 extends Father<Integer,String>{}
//子类保留父类的泛型
    //(1)全部保留
class son3<T1,T2> extends Father<T1,T2>{}
    //(2)部分保留
class son4<T2> extends Father<Integer,T2>{}
class Father<T1,T2>{}
//子类不保留父类的泛型
    //(1)没有类型,擦除
class son1<A,B> extends Father{}  //子类另外指明泛型
    //(2)具体类型
class son2<A,B> extends Father<Integer,String>{}
//子类保留父类的泛型
    //(1)全部保留
class son3<T1,T2,A,B> extends Father<T1,T2>{}
    //(2)部分保留
class son4<T2,A,B> extends Father<Integer,T2>{}

三、泛型类

/**
 * 泛型方法:不一定要在泛型类中定义;在方法的返回值前定义了泛型的标记
 *          可以声明为static,因为在调用该方法时才确定泛型参数的类型,而不是在实例化确定
 */

在Order泛型类中声明一个泛型方法,其中泛型方法的泛型参数E与该类的泛型参数T没有关系 

泛型方法1:

    //返回值是一个List,并且声明为泛型结构
    //传入T类型的数组:比如形参int[] arr 则返回值为int型的集合
    //此处可以将该方法声明为static,因为泛型方法与所处的类没有关系,在该方法调用的时候才确定泛型参数的类型
    public static <E> List<E> show(E[] arr){
        ArrayList<E> list = new ArrayList<>();
        for(E t : arr){  //遍历arr,并将arr的每一值赋给T类型的变量t
            list.add(t);  //将变量t添加到集合list中去
        }
        return list;
    }
    //测试泛型方法
    @Test
    public void test(){
        //泛型类指明为String类型
        Order<String> order = new Order<>();
        //声明一个double型的数组
        Double[] arr = {1.0, 2.0, 4.5, 6.8};
        //调用泛型类中的泛型方法,在调用时,指明泛型参数的类型
        List<Double> list = order.show(arr);//与类的泛型参数可以无关
        System.out.println(list);  //[1.0, 2.0, 4.5, 6.8]
    }

泛型方法2:

    //定义返回值类型为A的泛型方法
    public <A> A method(A a){
        return a;
    }
        //调用泛型方法
        int i = 6;
        System.out.println(order.method(i)); //6

四、通配符

一般形式的通配符:

/**
 * 通配符的使用:
 *      通配符:?
 *      类A是类B的父类,G<A>和G<B>是无关系的,二者共同的父类是G<?>   G<A>:泛型参数为A类型
 */
        List<Object> list1 = null;
        List<String> list2 = null;

        List<?> list = null;
        //比如:Object是String的父类,但是list1与list2没有关系,而list可作为list1与list2共同的        
        父类,从而进行赋值操作,相当于向上转型
        list = list1;
        list = list2;
        List<String> list3 = new ArrayList<>();  //List接口实例化,泛型类型为String类型
        list3.add("aa");
        list3.add("ab");
        list3.add("bb");
        list = list3;
        //对于list<?>不能添加数据,但可以添加null
        list.add(null);
        //获取,获取到的数据类型为Object
        Object o = list.get(0); //赋给最高级父类(防止传进来的参数类型低于接收的类型,从而报错)
        System.out.println(o);

有限制条件的通配符:

/**
 * 有限制条件的通配符
 * ? extends A
 *      G<? extends A> 可以作为G<A> 和 G<B>的父类,其中B是A的子类
 *
 * ? super A
 *      G<? extends A> 可以作为G<A> 和 G<B>的父类,其中B是A的父类
 */
public class GenericTest3 {
    @Test
    public void test(){
        List<? extends Person> list1 = null;
        List<? super Person> list2 = null;

        List<Student> list3 = null;
        List<Person> list4 = null;
        List<Object> list5 = null;
        //list1只能接收Person或它的子类 类型的结构(在读取数据时,接收类型要是最高的级别)
        list1 = list3;
        list1 = list4;
//        list1 = list5;  错误

        //list2只能接收Person或它的父类Object 类型的数据(在读取数据时,接收类型要是最高的级别)
//        list2 = list3;  错误
        list2 = list4;
        list2 = list5;
    }
}

class Person{}
class Student extends Person{}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值