java笔记_泛型

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

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

public interface Comparable{
    public int compareTo(Object o)
}

==>

public interface Compareble<T>{
    public int compareTo<T>(Object o)
}

表示泛型类型,可以用一个实际具体类型来替换它,称之为泛型实例化。

注意: 泛型类必须是引用类型。不能使用int、double或char这样的基本类型替换泛型类型。
如:

ArrayList<int> intList = new ArrayList<>();   // 错误
ArrayList<Integer> intList = new ArrayList<>(); // 正确

泛型方法

格式:

public <泛型类型> 返回类型 方法名(泛型类型 .)

规则:

  1. 都有一个类型参数声明部分位于方法返回类型之前
  2. 类型声明部分包含一个或多个类型参数,之间用逗号隔开
  3. 类型参数只能代表引用型类型,不能实原始类型

示例:

public class GenericMethodTest {
    //泛型方法
    public static <E> void printArray(E[] inputArray){
        for(E element : inputArray){
            System.out.printf("%s ",element);
        }
        System.out.println();
    }

    public static void main(String args[]){
        //创建不同类型数组: Integer,Double 和 Character
        Integer[] intArray = {1, 2, 3, 4, 5};
        Double[] doubleArray = {1.1, 2.2, 3.3, 4.4};
        Character[] charArray = {'H', 'E', 'L', 'L', 'O'};

        System.out.println("整型数组元素为:");
        printArray(intArray);

        System.out.println("\n双精度数组元素为:");
        printArray(doubleArray);

        System.out.println("\n字符型数组元素为:");
        printArray(charArray);
    }
}

泛型类

泛型类声明除在类名后面多了类型参数声明部分以外,其他的和非泛型类的声明类似。

格式

public class 类名<泛型类型1,...>

示例:

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<Integer> integerBox= new Box<Integer>();
        Box<String> stringBox = new Box<String>();

        integerBox.add(new Integer(10));
        stringBox.add(new String("hello world"));

        System.out.printf("整型值为: %d\n\n", integerBox.get());
        System.out.printf("字符串: s%\n\n", stringBox.get());
    }
}

注释

  • E: 集合的元素类型
  • K和V: 表的关键字与值得类型
  • T(U 和 S): 任意类型

通配泛型

  1. :任意类型

    public class GenericTest{
        public static void main(String[] args){
            List<String> name = new ArrayList<String>();
            List<Integer> age = new ArrayList<Integer>();
            List<Number> number = new ArrayList<Number>();
    
            name.add("icon");
            age.add(18);
            number.add(314);
    
            getData(name);
            getData(age);
            getData(number);
        }
    
        public static void getData(List<?> data){
            System.out.println("data: " + data.get(0));
        }
    }
  2. ? extends E:向下限定,E及其子类

    public class GenericTest{
        public static void main(String[] args){
            List<String> name = new ArrayList<String>();
            List<Integer> age = new ArrayList<Integer>();
            List<Number> number = new ArrayList<Number>();
    
            name.add("icon");
            age.add(18);
            number.add(314);
    
            getExtendNumber(name); // 编译报错
            getExtendNumber(age);
            getExtendNumber(number);
        }
    
        public static void getData(List<?> data){
            System.out.println("data: " + data.get(0));
        }
    
        public static void getExtendNumber(List<? extends Number> data){
            System.out.println("data: " + data.get(0));
        }
    }
  1. ?super E:向上限定,E及其父类

    public class GenericTest{
        public static void main(String[] args){
            List<Object> obj = new ArrayList<>();
            List<String> name = new ArrayList<String>();
            List<Integer> age = new ArrayList<Integer>();
            List<Number> number = new ArrayList<Number>();
    
            obj.add("object");
            name.add("icon");
            age.add(18);
            number.add(314);
    
            getExtendNumber(obj)
            getUperNumber(name); // 编译报错
            getUperNumber(age); // 编译报错
            getUperNumber(number);
        }
    
        public static void getData(List<?> data){
            System.out.println("data: " + data.get(0));
        }
    
        public static void getUperNumber(List<? super Number> data){
            System.out.println("data: " + data.get(0));
        }
    }

泛型的消除与限制

编译器使用泛型信息来编译代码,一旦编译器确认泛型类型是安全使用的,就会将它转换为原始类型。

ArrayList<String> list = new ArrayList<>();
list.add("wjqixige");
String state = list.get(0);

编译通过后会转换为原始类型 ==>

ArrayLis list = new ArrayList<>();
list.add("wjqixige");
String state = (String)(list.get(0));

由于泛型类存在运行时被消除,所以在使用泛型类的时候由一些限制:

  1. 不能使用泛型类型参数来创建实例
  2. 不能使用泛型类型参数类创建数组
  3. 不能在静态环境中使用类的泛型类型参数
  4. 在异常类中不能使用泛型类型参数

参考资料

java语言程序设计(进阶篇) Y.Daniel Liange 著 机械工业出版社

-------------本文结束感谢您的阅读-------------
Mr.wj wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!