• 泛型


    1.为什么要使用泛型程序设计?

    答:泛型程序设计意味着编写的代码可以被不同类型的对象重用。泛型之前,泛型程序设计使用继承实现的。例如:ArrayList类只维护一个Object引用的数组。但是,在获取值时,必须进行强制类型转换。二,可以向数组添加任何类的对象,因为不会进行错误检查。而泛型提供了类型参数来只是元素类型。

    2.通配符类型(wildcard type):

    通配符,加上限定用于解决父类引用可以容纳子类对象,而子类引用不能容纳父类对象。

    3.简单泛型类:

    public class Pair<T>{}

    public class Pair<T,U>{}

    类型变量用大写形式。在java库中,E表示集合的元素类型;K和V表示键值对;T,U,S表示任意类型。

    4.泛型方法:

    public static <T> T getMiddle(T... a){}

    类型变量放在修饰符(public static等)后面,返回类型的前面。

    5.类型变量的限定

    public static <T extends Comparable> T min(T[] a){}

    T只能是实现Comparable接口的类型。使用extends而不用implements原因:T应该是绑定类型的子类型。绑定类型可以是类,也可以是接口,选择extends是因为它更接近子类概念。并且也不打算添加新的关键字。不同的变量类型使用逗号隔开。当发生多个限定时使用&连接,并且一般标签接口(没有方法的接口)写在后面。因为在虚拟机中没有泛型,只有普通的类和接口,所以需要找到泛型的限定类作为变量类型(编译器在必要时要向其他强制转换)。无论什么时候定义一个泛型类型,都自动提供一个相应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定类型的变量用Object)。

    6.翻译泛型表达式

    先对原始方法调用,在进行类型强制转换。

    java代码中不能出现具有相同参数类型的两个方法。但虚拟机中用参数类型和返回类型可以确定一个方法。

    7.桥方法

    指定一个更严格的返回类型。

    Object get();->Employee get((Employee)get())

    约束与局限性:

    1.不能用基本类型实例化参数类型。原因是类型擦除,当类型擦除后,一般类型为Object,而Object类型的域不能存储double等基本类型的值,但是可以实例化Double,Double继承自Object,多以可以接受Double类型的值。

    2.运行时类型查询只适用于原始类型。虚拟机中的对象总有一个特定的非泛型类型,因此,所有的类型查询只产生原始类型。Pair<String> stringPair = ...;Pair<Employee> employeePair = ...;stringPair.getClass() == employeePair.getClass()是true。都返回Pair.class。

    3.不能创建参数化类型的数组,例如:Pair<String> table = new Pair<String>[10];是错误的。(正常情况下,数组可以记住他的元素类型,如果试图存储其他类型的元素,就会抛出一个ArrayStoreException异常。对于泛型来说,擦除会使这种机制无效。),所以不允许创建参数化类型的数组。可以使用统配类型的数组,然后进行类型转换:Pair<String>[] table = (Pair<String>) new Pair<?>[10];结果不安全,对table[0]调用一个String方法,会得到一个ClassCastException异常。只有一种安全有效的方法:使用ArrayList:ArrayList<Pair<String>>。

    4.varargs警告(向参数个数可变的方法中传递一个泛型类型的实例)

    public static <T> void addAll(Collection<T> , T... ts){for(t:ts)coll.add(t);}

    ts是一个数组。Collection<Pair<String>> table = ...;

    Pair<String> pair1 = ...;

    Pair<String> pair2 = ...;

    addAll(table,pair1,pair2);

    为了调用这个方法,java虚拟机必须建立一个Pair<String>数组,违反了第三条原则。对于这种情况规则有所放松,只会得到一个警告,而不是错误。可以采用@SuppressWarnings("unchecked")或者@SafeVarargs标注方法。

    5.不能实例化类型变量

    不能使用new T(...),new T[...]或者T.class这样的表达式。可以通过反射调用Class.newInstance方法来构造泛型对象。例如:

    public static <T> Pair<T> makePair(Class<T> cl){

      try{return new Pair<T>(cl.newInstance(),cl.newInstance())}

      catch(Exception ex){return null;}

    }

    6.不能构造一个泛型数组:

    public static <T extends Comparable> T[] minmax(T[] a){T[] mm = new T[2];...}//Error

    类型擦除会让这个方法永远创建Object[2]数组。

    如果数组仅仅作为一个类的私有实例域,就可以将这个数组声明为Object[],并且在获取元素是进行类型转换。

    7.泛型类的静态上下文中类型变量无效

    不能在静态域或方法中引用类型变量。类静态方法必须在声明时赋值或者实例化。但此时还不知道到底是什么类型,所以禁止使用带有类型变量的静态域和方法。

    8.不能抛出或捕获泛型类的实例。

  • 相关阅读:
    Python 爬虫js加密破解(一) 爬取今日头条as cp 算法 解密
    Python 爬虫实例(2)—— 爬取今日头条
    Python 爬虫实例(1)—— 爬取百度图片
    python 操作redis之——HyperLogLog (八)
    python 操作redis之——有序集合(sorted set) (七)
    Python操作redis系列之 列表(list) (五)
    Python操作redis系列以 哈希(Hash)命令详解(四)
    Python操作redis字符串(String)详解 (三)
    How to Install MySQL on CentOS 7
    Linux SSH远程文件/目录 传输
  • 原文地址:https://www.cnblogs.com/wongem/p/6672406.html
Copyright © 2020-2023  润新知