Java

泛型基础二

2020-04-24  本文已影响0人  静享时光

如果不明白为什么要使用泛型,使用泛型的好处,以及泛型类,泛型接口,泛型方法等知识,请移步泛型基础一

通配符

上界通配符

上界通配符就是限制类型参数是某个类本身或者是其子类。
例如

  public void dealData2(List<? extends Number> data) {
        /**
         * 
         */
    }
下界通配符

下界通配符:传入的泛型类型必须是“?”后面指定类型的父类,包括超类Object,以及它自身。

public void dealData(List<? super Number> data) {
        /**
         *
         */
    }
无界通配符

无界通配符,就是参数可以是任意类型。
有两种情况,无界通配符是一种有用的方法:
1、如果你正在编写可以使用 Object 类中提供的功能来实现的方法。
2、当代码使用泛型类中不依赖于类型形参的方法时。例如,List.size 或 List.clear。实际上,Class<?> 经常被使用,因为 Class<T> 中的大多数方法都不依赖于 T。

下面是不使用通配符和使用无界通配符的区别。

/**
 * 不使用通配符
 *
 * @param dataList
 */
public void printData(List<Object> dataList) {
    for (Object element : dataList) {

    }
}

我们可以在测试方法中报错了。


不适用通配符.png

是因为List<Integer>不是List<Object>的子类,而printData方法中需要的是List<Object>类型,所以会报错。
我们看下使用通配符的情况:


使用通配符.png
可以看到使用通配符之后是没有报错的。

通配符使用原则

   public void test() {
        List<String> src = new ArrayList<>();
        List<String> dest = new ArrayList<>();
        //public static <T> void copy (List < ? super T > dest, List < ? extends T > src)
        Collections.copy(dest, src);
    }

我们可以把变量分为In变量和Out变量。
In变量是提供数据,例如上例中的src。src参数提供要复制的数据,所以是In参数。
Out变量保存数据以供其他地方使用,例如上例中的dest。dest参数接收数据,所以是Out参数。
通配符的使用指南:
1、In变量是使用上界通配符定义,使用extends关键字。
2、Out变量是使用下界通配符定义,使用super关键字。
3、如果可以使用Object类中定义的方法访问In变量,请使用无界通配符。
4、在代码需要访问In和Out变量的情况下,不要使用通配符。

对泛型的限制

无法使用基本数据类型实例化泛型类型
原则一.png

Type argument cannot be of primitive type
类型参数不能是基元类型

无法创建类型形参的实例

泛型不能创建实例,是因为不知道泛型具体的类型


原则二.png

Type parameter 'T' cannot be instantiated directly
类型参数'T'不能直接实例化

无法声明类型为类型形参的静态字段

翻译一下就是用类型形参声明的成员变量不能用static修饰。


原则三.png

类的静态字段是类的所有非静态对象共享的类级变量。因此,不允许使用类型形参的静态字段。考虑以下类:

public class MobileDevice<T> {
    private static T os;

    // ...
}

如果允许类型形参的静态字段,则以下代码将混淆:

MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();
因为静态字段 os 由 phone,pager 和 pc 共享,所以 os 的实际类型是什么?它不能同时为 Smartphone,Pager 和 TabletPC。因此,你无法创建类型形参的静态字段。

不能使用参数化类型进行类型转换或者使用instanceof
原则四.png

Illegal generic type for instanceof
instanceof的泛型类型不合法


原则四-1.png

Inconvertible types; cannot cast 'java.util.List<java.lang.Integer>' to 'java.util.List<java.lang.Number>'
不可转换的类型;不能将'java.util.List<java.lang.Integer>'转换为'java.util.List<java.lang.Number>

无法创建参数化类型的数组

泛型不能是数组,是因为数组具有协变的性质。也就是说
如果A extends B
则 A[]也是B[]的子类。
如果数组是泛型的话,在泛型擦除之后就不满足A[]是B[]的子类了。

无法创建,捕获或者抛出参数化类型的对象
原则6.png
无法重载每个重载的形式参数类型擦除到相同原始类型的方法
原则7.png
上一篇 下一篇

猜你喜欢

热点阅读