Java重点--泛型

Posted 几分醉意.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java重点--泛型相关的知识,希望对你有一定的参考价值。

文章目录

💖泛型的概念

泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型,泛型也可以看做是一个变量,用来接收数据类型。
E e:Element元素
T t:Type 类型

✨使用泛型的好处与弊端

众所周知,凡是都有两面性,首先我们来谈谈不使用泛型的好处与坏处。

创建集合对象,不使用泛型
      好处:
            集合不使用泛型,默认的类型是Object类型,可以存储任意类型数据。
      坏处:
            不安全,会引发异常。

举例说明

private static void show01() 
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add(3);
        //使用迭代器遍历list集合
        //获取迭代器
        Iterator it = list.iterator();
        //使用迭代器中的方法hasNext和next遍历集合
        while (it.hasNext())
            //存的时候是Object类型,取出的时候也是Object
            Object obj = it.next();
            System.out.println(obj);
          //目前没问题

        //想要使用String类特有的方法,length获取字符串长度;不能使用 多态 Object obj = "abc";
        // 不能使用子类特有的方法 需要向下转型
//        String s = (String)obj;  //数字不能转换字符串 引发异常
//        System.out.println(s.length());

    

那么我们接下来在来谈谈使用泛型的好处与坏处。


创建集合对象,使用泛型

        好处:
            1.避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型
            2.把运行期异常(代码运行之后会抛出的异常),提升到了编译器(写代码的时候会报错)
        弊端:
            泛型是什么类型,只能存储什么类型的数据

举例说明

private static void show02() 
        ArrayList<String> list = new ArrayList<>();
        list.add("abc");

        //使用迭代器遍历list集合
        Iterator<String> it = list.iterator();
        while (it.hasNext())
            String next = it.next();
            System.out.println(next+"->"+next.length()); //abc->3
        
    

✨定义和使用含有泛型的类

定义一个含有泛型的类,模拟ArrayList集合
泛型是一个未知的数据类型,当我们不确定什么什么数据类型的时候,可以使用泛型泛型可以接收任意的数据类型,可以使用Integer,String,Student…创建对象的时候确定泛型的数据类型

好处 :类型不写死,创建对象泛型是什么类型,类中泛型就是什么类型

首先定义一个含有泛型的类

public class 含有泛型的类 <E> 
    private E name;

    public E getName() 
        return name;
    

    public void setName(E name) 
        this.name = name;
    
    //所有使用数据类型的时候,都使用了泛型E


接着就可以在主方法中使用它了

public class 主方法 
    public static void main(String[] args) 
        //不写泛型默认Object类型
        含有泛型的类<Object> aa = new 含有泛型的类<>();
        aa.setName("字符串");
        Object name = aa.getName();
        System.out.println(name);

        // 创建含有泛型的类对象,泛型使用Intergr
        // 创建对象的时候,确定泛型类型
        含有泛型的类<Integer> aa1 = new 含有泛型的类();
        aa1.setName(21);
        Integer name1 = aa1.getName();
        System.out.println(name1);

        // 创建含有泛型的类对象,泛型使用String
        含有泛型的类<String> aa2 = new 含有泛型的类();
        aa2.setName("字符串");
        String name2 = aa2.getName();
        System.out.println(name2);
    


✨定义和使用含有泛型的方法

定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间

格式:
修饰符<泛型> 返回值类型 方法名(参数列表(使用泛型))方法体;

含有泛型的方法,在调用方法的时候确定泛型的数据类型,传递什么类型的参数,泛型就是什么类型。

举例说明

定义含有泛型的方法

public class 泛型方法 

    //定义一个含有泛型的方法
    // M那个写什么都行
    public <M> void method01(M m)
        System.out.println(m);
    

    //定义一个含有泛型的静态方法
    public static <S> void method02(S s)
        System.out.println(s);
    


使用含有泛型的方法

public class 主方法 
    public static void main(String[] args) 
        // 创建泛型方法对象
        泛型方法 aa = new 泛型方法();

        /*
            调用含有泛型的方法method01
            传递什么类型,泛型就是什么类型
         */
        aa.method01(1);
        aa.method01("爱睡觉");
        aa.method01(3.3);
        aa.method01(true);

        aa.method02("静态方法,不建议创建对象使用");
        // 静态方法,通过类名.方法名(参数) 可以直接使用
        泛型方法.method02(33); //它也可以传递任意数据类型
    


✨定义和使用含有泛型的接口

含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型。例如:

Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法默认就是String
    public final class Scanner implements Iterator<String>
        public String next()
    

含有泛型接口第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,实现类跟着接口走,就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型。

那么接下来我们就举例演示一下

首先定义含有泛型的接口

public interface 接口 <I>
    public abstract void method(I i);

第一种使用方式

public class 实现类1 implements 接口<String> //实现类指定泛型类型
    @Override
    public void method(String s) 
        System.out.println(s);
    

第二种使用方式

public class 实现类2<I> implements 接口<I> //接口使用什么泛型 实现类就使用什么泛型
    @Override
    public void method(I i) 
        System.out.println(i);
    

测试含有泛型的接口


public class 主方法 
    public static void main(String[] args) 
        //创建实现类1对象
        实现类1 aa =new 实现类1();
        aa.method("字符串");

        //创建实现类2对象 创建对象的时候,指定什么泛型 就是什么泛型
        实现类2<Integer> bb =new 实现类2();
        bb.method(22);

        实现类2<Double> cc =new 实现类2();
        cc.method(2.2);

        // 跟定义含有泛型的类是一样的
    


✨泛型的通配符



举例说明

public class 泛型的通配符 
    public static void main(String[] args) 
        ArrayList<Integer> list1 = new ArrayList<>();
        list1.add(1);
        list1.add(2);

        ArrayList<String> list2 = new ArrayList<>();
        list2.add("a");
        list2.add("b");

        aa(list1);
        aa(list2);

//        ArrayList<?> list3 = new ArrayList<>(?); 定义的时候不能用通配符,作为参数传递的时候可以用
    

    /*
            第一一个方法,能遍历所有类型的ArrayList集合
            这时候我们不知道ArrayList集合使用什么数据类型,可以使用泛型通配符“?” 来接收数据类型
            注意:
                泛型没有继承概念的 里面不能写Object
         */
    public static void aa(ArrayList<?> list) // ArrayList<?> list作为参数传递,使用通配符
        //使用迭代器 遍历集合
        Iterator<?> it = list.iterator();
        while (it.hasNext())
            Object obj = it.next(); // 取出类型是Object类型,只要Object才能接收任意类型
            System.out.println(obj);
        
    


✨通配符的高级使用–受限泛型


泛型的上限限定:? extends E 代表使用的泛型只能是E类型的子类/本身
泛型的下限定:? super E 代表使用的泛型只能是E类型的父类/本身

✨斗地主小案例

按照斗地主的规则,完成洗牌发牌动作。
具体规则: 使用54张牌打乱顺序,三个玩家参与游戏,三人交替摸排,每人17张牌,最后留三张作底牌
代码实战

public class 斗地主案例 
    public static void main(String[] args) 
        //1. 准备54张牌,存储到一个集合中
        //创建集合
        ArrayList<String> list = new ArrayList();
        // 定义一个数组,用来存储花色
        String [] aa = "♠","♥","♣","♦";
        // 定义一个数组,用来存储序号
        String [] bb = "2","A","K","Q","J","10","9","8","7","6","5","4","3";
        //把大小王加入到集合中
        list.add("大王");
        list.add("小王");
        // 循环嵌套遍历两个数组,组装52张牌
        for (String s : aa) 
            for (String s1 : bb) 
//                System.out.println(s+s1);
                list.add(s+s1);
            
        
//        System.out.println(list);

        //2. 洗牌
        // 使用集合工具类Collections的方法
        //static void shuffle(List<?> list) 使用指定的随机源对指定列表进行置换,
        // 会随机打乱集合中的元素顺序
        Collections.shuffle(list);

        //3.发牌
        //定义四个集合存储三个玩家的牌和底牌
        ArrayList<String> aa1 = new ArrayList<>(); //玩家1
        ArrayList<String> aa2 = new ArrayList<>();//玩家2
        ArrayList<String> aa3 = new ArrayList<>();//玩家3
        ArrayList<String> aa4 = new ArrayList<>();//底牌
        //
        for (int i = 0; i < list.size(); i++) 
            //获取每一张牌
            String s = list.get(i);
            //轮流发牌
            if (i>=51)
                //给底牌发牌
                aa4.add(s);
            else if (i%3==0)
                //给玩家1发牌
                aa1.add(s);
            else if (i%3==1)
                //给玩家2发牌
                aa2.add(s);
            else if (i%3==2)
                //给玩家3发牌
                aa3.add(s);
            
        

        // 看牌
        System.out.println("张三"+aa1);
        System.out.println("李四"+aa2);
        System.out.println("麻子"+aa3);
        System.out.println("底牌"+aa4);

    


输出结果

以上是关于Java重点--泛型的主要内容,如果未能解决你的问题,请参考以下文章

斗地主2.0

模拟斗地主洗牌发牌

重点知识学习--[泛型学习]

Java高级——泛型

java_泛型(2016-11-17)

Java ——泛型 序列化