zoukankan      html  css  js  c++  java
  • java-泛型

    编写泛型

    泛型(Generic)一般用在集合类中 编写泛型时,需要定义泛型类型

    public class Pair<T> { … }
    

    静态方法不能引用泛型类型,必须定义其他类型来实现“泛型”

    public static <K> Pair<K> create(K first, K last) { … }
    

    泛型可以同时定义多种类型<T, K>。

    public class Pair<T,K> { … }
    

    擦拭法

    擦拭法

    • Java的泛型(Generic)是采用擦拭法(Type Erasure)实现的。

    • 编译把视为Object

    • 编译器根据实现安全的强制转型

        我们写的是
        public static void main(String[] args) {
        	Pair<String> pair = new Pair<>("xiao","ming");
        	String first = pair.getFirst();
        }
      
        实际上编译器处理的是
        public static void main(String[] args) {
        	Pair pair = new Pair("xiao","ming");
        	String first = (String)pair.getFirst();
        }
      

    擦拭法的局限:

    • 不能是基本类型,例如int

    • Object字段无法持有基本类型

    • 无法取得带泛型的Class(返回的永远的同一个Class) 如:Pair<String>.class

    • 无法判断带泛型类型的类型,例如:x instanceof Pair<String>

    • 不能实例化 T 类型 如:new T();

    • 可以继承自泛型类:

        public class IntPair extends Pair<Integer> {
        }
      
    • 泛型方法要防止重复定义,例如: public boolean equals(T obj)

    • 子类可以获取父类的泛型类型。

    继承关系:

    Type
    |
    +- Class
    |
    +- ParameterizedType
    |
    +- GenericArrayType
    |
    +- WildcardType


    extends通配符

    使用类似<? extends Number>通配符作为方法参数时

    void someMethod(List<? extends Number> list) {
     Number n = list.get(0);
     list.add(n); // ERROR
    }
    允许传入List<Number>,List<Integer>,List<Double>...
    允许调用方法获取Number类型
    不允许调用方法传入Number类型(null除外)
    

    <T extends Number>定义泛型类

    定义泛型时可以通过extends限定T必须是Number或Number的子类
    

    super通配符

    使用类似<? super Integer>通配符作为方法参数时表示:

    • 允许传入List<Integer>List<Number>List<Object>

    • 允许调用方法传入Integer类型 set方法

    • 不允许调用方法获取Integer类型(Object除外)get方法

        void someMethod(List<? super Integer> list) {
        	list.add(123);
        	Integer n = list.get(0); // ERROR
        }
      

    使用类似定义泛型类型时表示:

    • 泛型限定为Integer或Integer的超类

    extends和super通配符的区别

    • 允许调用方法获取T的引用
    • 允许调用方法传入T的引用

    无限定通配符<?>

    • 只能获取Object引用

    • 只能传入null

    • 可以用消除<?>


    泛型和反射

    部分反射API是泛型:

    • Class

        Class clazz = String.class;
        String str = (String) clazz.newInstance();
      
        Class<String> clazz = String.class;
        String str = clazz.newInstance();
      
        Class<? super String> sup = clazz.getSuperclass();
      
    • Constructor

        Class<Integer> clazz = Integer.class();
        Constructor<Integer> cons = clazz.getConstructor(int.class);
        Integer i = cons.newInstance(123);
      
    • 可以声明带泛型的数组,但不能直接创建带泛型的数组,必须强制转型

        Pair<String> [] ps = null;					//正确
        Pair<String> [] ps = new Pair<String>[2];  	//错误
        
        @suppressWarnings("unchecked")
        Pair<String>[] ps = (Pair<String>[]) new Pair[2];  //正确
      
      • 不安全的使用带泛型的数组:

          public static void main(String[] args) {
          	Pair[] arr = new Pair[2];
          	Pair<String>[] ps = (Pair<String>[])arr;
          	
          	ps[0] = new Pair<String>("a","b");
          	arr[1] = new Pair<Integer>(1,2);
          	
          	
          	try {
          		//ClassCastException
          		Pair<String> p = ps[1];
          		
          	} catch (Exception e) {
          		System.err.println(e.getMessage()); //java.lang.Integer cannot be cast to java.lang.String
          	}
          }
        
      • 安全的使用带泛型的数组:

          @suppressWarnings("")
          Pair<String>[] ps = (Pair<String>[]) new Pair[2]; 
        
      • 带泛型的数组实际上是编译器进行类型的擦除

          Pair[] arr = new Pair[2];
          Pair<String>[] ps = (Pair<String>[]) arr;
          
          System.out.println(ps.getClass()==Pair[].class);//true
        
          String s1 = (String) arr[0].getFirst();
          String s2 = ps[0].getFirst();
        
    • 可以通过Array.newInstance(Class, int)创建T[]数组,需要强制转型

      • 不能直接创建T[]数组,擦拭后代码变为new Object[]

          //compile error:
          public class Abc<T>{
          	T[] createArray(){
          		return new T[5];
          	}
          }
        
      • 借助Class

          public class Abc<T>{
          	T[] createArray(Class<T> cls){
          		return (T[])Array.newInstance(cls,5);
          	}
          }
          
          //使用
          String[] s = new Abc<String>().createArray(String.class);
        
      • 利用可变参数创建T[]数组,@SafeVarargs消除编译警告

          public class ArrayHelper{
          	@SafeVarargs				
          	static <T> T[] asArray(T... objs){
          		return objs;
          	}
        
          	public static void main(String[] args) {
          		String[] ss = asArray("a","B","c");
          	}
          }
  • 相关阅读:
    Two strings CodeForces
    Dasha and Photos CodeForces
    Largest Beautiful Number CodeForces
    Timetable CodeForces
    Financiers Game CodeForces
    AC日记——整理药名 openjudge 1.7 15
    AC日记——大小写字母互换 openjudge 1.7 14
    AC日记——将字符串中的小写字母换成大写字母 openjudge 1.7 13
    AC日记——加密的病历单 openjudge 1.7 12
    AC日记——潜伏着 openjudge 1.7 11
  • 原文地址:https://www.cnblogs.com/rogersma/p/11495132.html
Copyright © 2011-2022 走看看