zoukankan      html  css  js  c++  java
  • 泛型

    1.概述

    集合中存储元素的数据类型

    集合中是可以存放任意对象的,只要把对象存储集合后,那么这时,他们都会被提升成Object类型。当我们在取出每一个对象,并且进行相应的操作,这时必须采用类型转换。

    泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型

    泛型也可以看成是一个变量,用来做数据类型。

      E e : Element 元素

      T t : Type 类型

    ArrayList集合在定义的时候,不知道集合中会存储什么类型的数据,所以类型使用泛型。

     E:未知的数据类型

    public class ArrayList<E> {

      public boolean add(E e) {}

      public E get(int index) {}

    }

    2.什么时候用泛型

    创建集合对象的时候,就会确定泛型的数据类型

    (1)

    ArrayList<String> list = new ArrayList<String>();

    这样会把数据类型作为参数,把String赋值给泛型E

    public class ArrayList<String> {

      public boolean add(String e) {}

      public String get(int index) {}

    }

    (2)

    ArrayList<Student> list = new ArrayList<Student>();

    这样会把数据类型作为参数,把Student赋值给泛型E

    public class ArrayList<Student> {

      public boolean add(Student e) {}

      public Student get(int index) {}

    }

    3.使用泛型和不使用泛型的区别

    创建集合对象,不使用泛型

    好处:

      集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据

    弊端:

      不安全,会引发异常

    不使用泛型的例子:

    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Demo01Generic {
        public static void main(String[] args) {
            show();
        }
        private static void show() {
            ArrayList list = new ArrayList();
            list.add("asb");
            list.add(1);
    
            // 使用迭代器遍历list集合
            // 获取迭代器
            Iterator iterator = list.iterator();
            // 使用迭代器中的方法hasNext和next遍历集合
            while(iterator.hasNext()){
                // 存的时候,数据类型是Object,取的时候元素也是Object类型
                Object obj = iterator.next();
                System.out.println(obj);
    
                // 想要使用String类特有的方法,length获取字符串的长度
                // 不能使用多态 Object obj = "abc"; 需要向下转型
                // 会抛出ClassCastException类型转换异常,不能把Integer类型转换为String类型
                String s = (String)obj;
                System.out.println(s.length());
            }
        }
    }
    

      运行结果:

     创建集合对象,使用了泛型的例子:

     好处:

    (1)避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型

    (2)把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候就会报错了)

    弊端:

    泛型是什么类型,只能存储什么类型的数据

     

     

     4.定义和使用泛型的类

    定义一个含有泛型的类,模拟ArrayList集合

    泛型是一个未知的数据类型,当我们不确定什么数据类型的时候,可以使用泛型

    泛型可以接收任意的数据类型,可以使用Integer,String,Student...

    创建对象的时候,确定泛型的数据类型

    未使用泛型:

     使用泛型:

     使用了泛型之后,这样创建对象的时候,想使用什么类型,就使用什么类型

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

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

    格式:

      修饰符<泛型> 返回值类型 方法名(参数列表(使用泛型)) {

        方法体;

    }

    含有泛型的方法,在调用方法的时候确定泛型的数据类型

    传递什么数据类型的参数,泛型就是什么类型

     运行结果:

     定义一个含有泛型的静态方法

     6.定义含有泛型的接口

        含有泛型的接口,第一种使用方式

      定义接口的实现类,实现接口,指定接口的泛型

        public interface Iterator<E> {

           E next();

        }

      Scanner类实现了Iterator接口,并指定接口的泛型为String,所以重写的next方法泛型默认为String

        public final Scanner implements Iterator<String> {

          public String next(){}

        }

     含有泛型的接口第二种使用方式

    接口使用什么泛型,实现类就使用什么泛型,类跟着接口走

    就相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型

    public interface List<E> {

      boolean add(E e);

      E get(int index);

    }

    public class ArrayList<E> implements List<E> {

      public boolean add(E e) {}

      public E get(int index) {}

    }

     7.泛型通配符

    当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符之后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。

    (1)通配符基本使用

    泛型的通配符:不知道使用什么类型来接收的时候,此时可以使用?,?表示未知通配符,代表任意的数据类型

    此时只能接收数据,不能往集合中存储数据

    使用方式

    不能创建对象使用

    只能作为方法的参数使用

     

     注意:泛型没有继承概念的

    package cn.yjg.day10.demo04;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    public class Demo05Genric {
        public static void main(String[] args) {
            ArrayList<Integer> list01 = new ArrayList<>();
            list01.add(1);
            list01.add(2);
    
            ArrayList<String> list02 = new ArrayList<>();
            list02.add("a");
            list02.add("b");
    
            printArray(list01);
            printArray(list02);
        }
    
        /*
        * 定义一个方法,能遍历所有类型的ArrayList集合
        * 这时候,我们不知道ArrayList集合使用什么数据类型,可以用泛型的通配符来接收数据
        * */
    
        public static void printArray(ArrayList<?> list) {
            // 使用迭代器遍历集合
            Iterator<?> iterator = list.iterator();
            while (iterator.hasNext()) {
                // iterator.next()方法,取出的元素是Object,可以接收任意的数据类型
                Object obj = iterator.next();
                System.out.println(obj);
            }
        }
    }
    

      运行结果:

     泛型通配符在定义时候不能用,参数传递时候可以用

     (2)通配符的高级使用

    之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置,但是在Java的泛型中可以知道一个泛型的上限和下限。

    泛型的上限:

    • 格式:类型名称 <? extends 类> 对象名称
    • 意义:只能接受该类型及其子类

    ? extends E       即代表使用的泛型只能是E类型的子类/本身

    泛型的下限:

    • 格式:类型名称 <? super 类> 对象名称
    • 意义:只能接受该类型及其父类

    ? super E    即代表使用的泛型只能是E类型的父类/本身

    比如,现在已知Object类,String类,Number类,Integer类,其中Number类是Integer的父类

    package cn.yjg.day10.demo04;
    
    import java.util.ArrayList;
    import java.util.Collection;
    
    public class Demo06Generic {
        public static void main(String[] args) {
            Collection<Integer> list1 = new ArrayList<>();
            Collection<String> list2 = new ArrayList<>();
            Collection<Number> list3 = new ArrayList<>();
            Collection<Object> list4 = new ArrayList<>();
            
            getElement1(list1);
            getElement1(list2);  // 报错
            getElement1(list3);
            getElement1(list4);  // 报错
    
            getElement2(list1);  // 报错
            getElement2(list2);  // 报错
            getElement2(list3);
            getElement2(list4);
            
            /*
                类与类之间的继承关系
                Integer extends Number extends Object
                String extends Object
            */
           
        }
        // 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
        public static void getElement1(Collection<? extends Number> coll) {}
        // 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
        public static void getElement2(Collection<? super Number> coll) {}
    }
    

     

  • 相关阅读:
    WeChall_Training: ASCII (Training, Encoding)
    WeChall_Prime Factory (Training, Math)Training: WWW-Robots (HTTP, Training)
    WeChall_Training: Crypto
    WeChall_ Training: Stegano I (Training, Stegano)
    WeChall_Training: Get Sourced (Training)
    WeChall_Prime Factory (Training, Math)
    [loj3246]Cave Paintings
    [luogu5423]Valleys
    [loj3247]Non-Decreasing Subsequences
    [luogu5426]Balancing Inversions
  • 原文地址:https://www.cnblogs.com/GumpYan/p/13815980.html
Copyright © 2011-2022 走看看