泛型方法(利用反射进行传递类型)

定义泛型方法语法格式

java-basic-generic-4.png

调用泛型方法语法格式 java-basic-generic-5.png

说明

  • 定义泛型方法时,必须在返回值前边加一个,来声明这是一个泛型方法,持有一个泛型T,然后才可以用泛型T作为方法的返回值。
  • Class的作用就是指明泛型的具体类型,而Class类型的变量c,可以用来创建泛型类的对象。
  • 为什么要用变量c来创建对象呢?既然是泛型方法,就代表着我们不知道具体的类型是什么,也不知道构造方法如何,因此没有办法去new一个对象,但可以利用变量c的newInstance方法去创建对象,也就是利用反射创建对象。
  • 泛型方法要求的参数是Class类型,而Class.forName()方法的返回值也是Class,因此可以用Class.forName()作为参数(直接读取配置文件properties)。其中,forName()方法中的参数是何种类型,返回的Class就是何种类型。在本例中,forName()方法中传入的是User类的完整路径,因此返回的是Class类型的对象,因此调用泛型方法时,变量c的类型就是Class,因此泛型方法中的泛型T就被指明为User,因此变量obj的类型为User。
  • 当然,泛型方法不是仅仅可以有一个参数Class,可以根据需要添加其他参数。

    泛型的上下限

  • 注意:泛型不支持多态

  • 先看下如下的代码,很明显是会报错的 ```java class A{} class B extends A {}

// 如下两个方法不会报错 public static void funA(A a) { // …
} public static void funB(B b) { funA(b); // …
}

// 如下funD方法会报错 public static void funC(List listA) { // …
} public static void funD(List listB) { funC(listB); // Unresolved compilation problem: The method doPrint(List
) in the type test is not applicable for the arguments (List) // …
}

  1. - 为了解决泛型中隐含的转换问题,Java泛型加入了类型参数的上下边界机制。
  2. - <? extends A>表示该类型参数可以是A(上边界)或者A的子类类型。编译时擦除到类型A,即用A类型代替类型参数。
  3. - 这种方法可以解决开始遇到的问题,编译器知道类型参数的范围,如果传入的实例类型B是在这个范围内的话允许转换,这时只要一次类型转换就可以了,运行时会把对象当做A的实例看待。
  4. ```java
  5. public static void funC(List<? extends A> listA) {
  6. // ...
  7. }
  8. public static void funD(List<B> listB) {
  9. funC(listB); // OK
  10. // ...
  11. }

泛型上下限的引入

  • 在使用泛型的时候,我们可以为传入的泛型类型实参进行上下边界的限制,如:类型实参只准传入某种类型的父类或某种类型的子类。
    上限
    class Info<T extends Number>{    // 此处泛型只能是数字类型
      private T var ;        // 定义泛型变量
      public void setVar(T var){
          this.var = var ;
      }
      public T getVar(){
          return this.var ;
      }
      public String toString(){    // 直接打印
          return this.var.toString() ;
      }
    }
    public class demo1{
      public static void main(String args[]){
          Info<Integer> i1 = new Info<Integer>() ;        // 声明Integer的泛型对象
      }
    }
    
    下限
    class Info<T>{
      private T var ;        // 定义泛型变量
      public void setVar(T var){
          this.var = var ;
      }
      public T getVar(){
          return this.var ;
      }
      public String toString(){    // 直接打印
          return this.var.toString() ;
      }
    }
    public class GenericsDemo21{
      public static void main(String args[]){
          Info<String> i1 = new Info<String>() ;        // 声明String的泛型对象
          Info<Object> i2 = new Info<Object>() ;        // 声明Object的泛型对象
          i1.setVar("hello") ;
          i2.setVar(new Object()) ;
          fun(i1) ;
          fun(i2) ;
      }
      public static void fun(Info<? super String> temp){    // 只能接收String或Object类型的泛型,String类的父类只有Object类
          System.out.print(temp + ", ") ;
      }
    }
    
    小结
    ```java <?> 无限制通配符 <? extends E> extends 关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类 <? super E> super 关键字声明了类型的下界,表示参数化的类型可能是指定的类型,或者是此类型的父类

// 使用原则《Effictive Java》 // 为了获得最大限度的灵活性,要在表示 生产者或者消费者 的输入参数上使用通配符,使用的规则就是:生产者有上限、消费者有下限

  1. 如果参数化类型表示一个 T 的生产者,使用 < ? extends T>;
  2. 如果它表示一个 T 的消费者,就使用 < ? super T>;
  3. 如果既是生产又是消费,那使用通配符就没什么意义了,因为你需要的是精确的参数类型。 ```

    深入理解泛型