• java 泛型


    一、概念

    Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。

    泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。

    1. 泛型方法

    具有一个或多个类型变量的方法,称之为泛型方法。类型变量也叫类型参数。

    语法:

    public static < E > void printArray( E[] e );
    public static <T extends Comparable<T>> T maximum(T x, T y, T z);//有界(上届)的类型参数

     规则:

    (1) 返回值之前类型变量声明;

    (2) 多个类型参数声明时用逗号隔开;

    (3) 泛型方法可以存在于非泛型类中;

    (4) 类型参数能被用来声明返回值类型;

    注意:类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。

     要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。

     有界的类型参数:

    要声明一个有界的类型参数,首先列出类型参数的名称,后跟extends关键字,最后紧跟它的上界。

     一个操作数字的方法可能只希望接受Number或者Number子类的实例. 

    2. 泛型类

    泛型类需要在类名后面添加了类型参数声明部分.

     语法:

    public class Box<T>;

    3. 类型通配符

    (1) 类型通配符一般是使用?代替具体的类型参数。

    语法:

    public static void getData(List<?> data);
    // 上届:通配符泛型只接受Number及其下层子类类型
    public static void getUperNumber(List<? extends Number> data);

    有界的类型参数:

    <? extends T>表示该通配符所代表的类型是T类型的子类。 [上限]
    <? super T>表示该通配符所代表的类型是T类型的父类。     [下限]

    4. 常用通配符

    常用以下字符表示参数类型:

    E - Element (在集合中使用,因为集合中存放的是元素)

    T - Type(Java 类)

    K - Key(键)

    V - Value(值)

    N - Number(数值类型)

    ? - 表示不确定的java类型

    S、U、V - 2nd、3rd、4th types

    5. T和?的区别

    T 是一个 确定的 类型,通常用于泛型类和泛型方法的定义,?是一个 不确定 的类型,通常用于泛型方法的调用代码和形参,不能用于定义类和泛型方法。

    区别1:通过 T 来 确保 泛型参数的一致性

    // 通过 T 来 确保 泛型参数的一致性
    public <T extends Number> void
    test(List<T> dest, List<T> src)
    
    //通配符是 不确定的,所以这个方法不能保证两个 List 具有相同的元素类型
    public void
    test(List<? extends Number> dest, List<? extends Number> src)

    区别2:类型参数可以多重限定而通配符不行
    使用 & 符号设定多重边界(Multi Bounds),指定泛型类型 T 必须是 MultiLimitInterfaceA 和 MultiLimitInterfaceB 的共有子类型,此时变量 t 就具有了所有限定的方法和属性。对于通配符来说,因为它不是一个确定的类型,所以不能进行多重限定。


    区别3:通配符可以使用超类限定而类型参数不行

    // 类型参数 T 只具有 一种 类型限定方式:
    T extends A
    
    // 但是通配符 ? 可以进行 两种限定:
    ? extends A
    ? super A

    6.Class<T> 和 Class<?> 区别

    Class<T>和 Class<?> 最常见的是在反射场景下的使用。

    // 通过反射的方式生成 multiLimit 对象,这里比较明显的是,我们需要使用强制类型转换
    MultiLimit multiLimit = (MultiLimit)Class.forName("com.atguigu.MultiLimit").newInstance();

    对于上述代码,在运行期,如果反射的类型不是 MultiLimit 类,那么一定会报 java.lang.ClassCastException 错误。

    对于这种情况,则可以使用下面的代码来代替,使得在在编译期就能直接检查到类型的问题:

    public class Test {
        public static <T> T getInstance(Class<T> cls) throws Exception {
            return cls.newInstance();
        }
    
        public static void main(String[] args) throws Exception {
            A a = getInstance(A.class);
            B b = getInstance(B.class);
        }
    }
    
    class A {}
    class B {}

    Class<T>在实例化的时候,T 要替换成具体类。Class<?>它是个通配泛型,? 可以代表任何类型,所以主要用于声明时的限制情况。比如,我们可以这样做申明:

    public class Test2<T> {
        // 可以
        public Class<?> clazz;
        // 不可以,因为 T 需要指定类型
        public Class<T> clazzT;
    }

    所以当不知道定声明什么类型的 Class 的时候可以定义一 个Class。

    那如果也想 public Class<T> clazzT;这样的话,就必须让当前的类也指定 T , 

    public class Test2<T> {
        // 可以
        public Class<?> clazz;
        // 不可以,因为 T 需要指定类型
        public Class<T> clazzT;
    }

    二、使用教程

    1. 泛型方法

    // 泛型方法 printArray
    public static <E> void printArray(E[] inputArray) {
        // 输出数组元素
        for (E element : inputArray) {
            System.out.printf("%s ", element);
        }
    }

    有界的泛型方法:

    // 比较三个值并返回最大值  参数的类型必须实现了Comparable接口,即必须是可比较的
    public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
        T max = x; // 假设x是初始最大值
        if (y.compareTo(max) > 0) {
            max = y; //y 更大
        }
        if (z.compareTo(max) > 0) {
            max = z; // 现在 z 更大
        }
        return max; // 返回最大对象
    }

    2. 泛型类

    public class Box<T> {
        private T t;
    
        public void add(T t) {
            this.t = t;
        }
    
        public T get() {
            return t;
        }
    
        public static void main(String[] args) {
            Box<String> stringBox = new Box<String>();
            stringBox.add(new String("陈数"));
            // 
    是换行符,使光标定位到下一行
            System.out.printf("字符串为 :%s
    ", stringBox.get());
        }
    }

    3. 类型通配符

    public static void getData(List<?> data) {
        System.out.println("data :" + data.get(0));
    }

    有上界的类型通配符:

    public static void getUperNumber(List<? extends Number> data) {
        System.out.println("data :" + data.get(0));
    }

     参考:

     java 泛型    

    Java泛型中E、T、K、V等的含义

    泛型通配符详解

  • 相关阅读:
    触摸屏网站开发系列(一)-ios web App应用程序(ios meta)
    jQuery Mobile 入门教程
    html的视频插件 (转)
    网页布局流式布局
    2.05-random-uesr-proxy
    2.04-proxy-handler
    2.03-handler_openner
    2.02-request_header_two
    2.01-request_header
    1.03-get_params2
  • 原文地址:https://www.cnblogs.com/shiyun32/p/9717929.html
Copyright © 2020-2023  润新知