泛型

什么是泛型?为什么使用泛型?

泛型的出现意味着编写的代码可以被不同类型的对象所重用,提升了代码的重用性。泛型的本质是参数化类型,即将所需操作的数据类型设置为一个参数。
举个实际中的栗子:我们需要设计一个柜子的类,柜子可以用于存放书本、食品或者衣物,但是我们在设计阶段不能确定柜子里具体要存放什么东西,那怎么来设计这样一个通用型的柜子,这里就可以用到泛型。所以,我们把存放元素的类型设计成一个参数,这个类型参数就称之为泛型。
举个JAVA中的栗子:ArrayList<T>,List<T>,这个<T>就是类型参数,也就是泛型。为什么这么写呢?因为我们在创建Arraylist或者List时,无法确定里面具体存储的元素的类型,但是我们有希望一个实例对象中存储的元素的类型时一致的,这就需要泛型来实现操作。

        int[] arr1 = new int[] {159,357,456};
        //没有用泛型,ArrayList中存储的元素格式各样,实际开发中在操作时是很容易出现问题的
        List list1 = new ArrayList();
        list1.add(123);
        list1.add("敲代码的阿茄");
        list1.add(arr1);
        //使用泛型,限制ArrayList存放的元素的类型,就不能添加存储其他类型的元素了
        List<String> list2 = new ArrayList<>();
        list2.add("敲");
        list2.add("代");
        list2.add("码");
        list2.add("的");
        list2.add("阿");
        list2.add("茄");
       //list2.add(123);//无法添加
       //list2.add(arr1);//无法添加

泛型使用的基本要求

  • 异常类不能声明为泛型。
  • 泛型不能是基本数据类型,需要使用基本数据类型的泛型可以写成其包装类。
        //List<int> list2 = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>();

自定义泛型类

在类或接口中声明的泛型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值。但是,不能在静态方法中使用类的泛型

    // 泛型类:类中定义有不确定的类型
    public class Dict<T> {
        String dictName;
        int dictCount;
        T dictT;
        //泛型类下用了泛型的方法,报错,需要去掉static
        //public static void get(T dictT) {
        //  this.dictT = dictT;
        //}
        //泛型类下没用泛型的方法
        public static void set() {
            System.out.println("");
        }
    }

泛型方法和泛型类下的方法?

泛型方法:该泛型方法所在的类可以不是泛型类。往直观一点讲,方法中出现了泛型结构<>。
那么,泛型方法可以是静态的吗?可以,因为泛型参数是在调用方法时确定的,并非在实例化时确定的。

      public class GenericTest {
            public static void main(String[] args) {
                Dict<Float> dict = new Dict<>();
                dict.set1(0.0f);
                //调用泛型方法,泛型类型跟类的泛型没关系,不受影响
                dict.set2(" ");
                dict.set2(36);
                dict.set2(new ArrayList());
            }
        }

        //泛型类
        class Dict<T> {
            String dictName;
            int dictCount;
            //泛型类中的方法:如果调用了泛型则不能为静态
            public  void set1(T dictT) {
                System.out.println("我是泛型类下的方法");
            }
            //泛型方法:可以为静态
            public  static <T> void set2(T dictT) {
                System.out.println("我是泛型方法");
            }
        }

泛型与继承

  • 如果类A是类B的父类,但是,G<A>不是G<B> 的父类(G是类或者接口),两个属于不同的类。所以不存在两者间的多态和向上转型。
  • 但是呢,A<G>仍然是B<G>的父类。

通配符

通配符:?
  • 利用通配符,创建二者的共同父类,G<A>G<B>的共同父类G<?>
  • 但是,不能往其中添加新数据,常用于赋值操作而已,仅能添加null;
  • 允许读取数据,读取数据的类型为object;

举例说明:定义List<?>List<Object>List<String>的公共父类。

        //不能添加数据,除了null
        List<?> list = new ArrayList<>();
        //list.add(16);//报错
        //list.add(" ");//报错
        list.add(null);
        //允许读取数据
        List<?> list = new ArrayList<>();
        List<String> list1 = new ArrayList<>();
        list1.add("newstring");
        list =list1;
        list.add(null);
        Object obj = list.get(0);
        System.out.println(obj);//newstring
有限制条件的通配符
  • G<? extends A>可以作为G<A>G<B>的父类,其中B是A的子类;即,可以作为所有继承于A类的类G<A的子类>的父类。
  • G<? super A>可以作为G<A>G<B>的父类,其中B是A的父类;即,可以作为所有A的父类的G<A的父类>的父类。
        // 下面举例类的关系:Earth extends Sun, Sun extends Universe
        List<? extends Sun> list1 = new ArrayList<>();// 可以作为List<Sun及其子类>的父类
        List<? super Sun> list2 = new ArrayList<>();// 可以作为List<Sun及其父类>的父类
        List<Universe> list3 = new ArrayList<>();
        List<Sun> list4 = new ArrayList<>();
        List<Earth> list5 = new ArrayList<>();
        list1 = list4;// 多态
        list2 = list4;//多态
        // 读取数据
        Sun s1 =list1.get(0);//获取的数据是Sun或者Sun的子类的对象,可以实现多态
        Earth e1 =(Earth)list1.get(0);//不强转会报错,因为获取的数据可能是Sun的对象,父类转子类需要强转
        Sun s2=(Sun)list2.get(0);//不强转会报错,获取的数据可能是Sun的父类,父类转子类需要强转
        Object o=list2.get(0);//不强转情况下,只能是Object
        // 写入数据
        list2.add(new Sun());//只能添加Sun本身,或者Sun的子类
        //因为list2存的可能是Sun及其父类,假设new的是Universe,但是list2中存储的是Sun,
        //即实际?=Sun,那么Universe作为父类是无法直接赋给子类的
        list2.add(new Earth());
        //list1.add();//无法添加数据,因为你无法确定存储的子类有多小
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、概述 在之前的27、【JavaSE】【Java 核心类库(上)】集合类-Collection[%5Bhttps...
    yscyber阅读 212评论 0 1
  • [toc] 一、为什么要有泛型 1.1泛型:标签 1.2 设计背景: 集合容器在设计阶段或声明阶段不能确定这个容器...
    bjfStart阅读 149评论 0 0
  • 1. 泛型的概念 1.1 什么是泛型 泛型类似标签,出现原因是因为:集合容器类在设计阶段/声明阶段不能确定这个容器...
    尔玉RGX阅读 233评论 0 1
  • java泛型解决容器,不确定类型问题,多个返回值,避免类型转换。 类泛型 类泛型定义的时候需要在类型后增加尖括号,...
    wangsye阅读 460评论 0 0
  • 写在之前 以下是《疯狂Java讲义》中的一些知识,如有错误,烦请指正。 泛型初衷 集合对元素类型没有任何限制,这样...
    hainingwyx阅读 400评论 0 0