Java泛型笔记

java 泛型

泛型的作用:在编译阶段检测非法的类型

泛型的本质:参数化类型,将数据类型指定为参数。

何时使用泛型?

普通的java方法能够接受的参数类型是被预先定义、固定类型的。

如果我们要调用同一个方法(相同方法名)但需要传入不同类型参数时就需要用到方法的重载,但重载需要为每一种可能的参数类型都重新编写一个方法。如果需要传入多种参数类型,这会大大增加开发工作量。

此时就可以通过泛型这个工具来将方法的参数类型 也 参数化,使方法能够动态的接受不同类型的参数,这样就无需再写多个重载的方法,大大减少了代码量。

根据传递给泛型方法的参数类型,编译器适当地处理每一个方法调用。泛型方法是面向编译器的

定义泛型方法的规则:

1.类型参数声明(由尖括号<>分隔),类型参数声明 应放置在 方法返回类型声明 之前

2.每一个 类型参数声明 包含一个或多个 类型参数(又称类型变量),参数间用逗号隔开。

3.类型参数 可以作为 返回值类型声明,能作为泛型方法得到的实际参数类型的占位符。

4.泛型方法体的声明和其他方法一样,类型参数只能传入引用型类型,不能是原始类型。

示例:

 public class GenericMethodTest {

  public static < E > void printArray( E[] inputArray ) {

    for ( E element : inputArray ){        

              System.out.printf( "%s ", element );

           }

           System.out.println();

  }

}

示例:

有界的类型参数:

  按照普通定义的泛型方法可接受所有类型的 参数, 当我们需要限定传入的参数类型范围时怎么办?如:在某个场景我只需要接收Number或者Number子类实例。这时我们的大神JDK设计师们就提供了 有界类型参数 来满足这种需求。

定义方法:

  在 类型参数名称 后加上 extends(不能是implements) 接限定类型的上界。

示例:

public class MaximumTest{

  public static <T extends Comparable<T>> T maximum(T xT yT z) {

    T max = x; // 假设x是初始最大值

        if ( y.compareTo( max ) > 0 ){

           max = y; //y 更大

        }

        if ( z.compareTo( max ) > 0 ){

           max = z; // 现在 z 更大           

        }

        return max; // 返回最大对象  

  }

  public static void main( String args[] )   {

        System.out.printf( "%d, %d 和 %d 中最大的数为 %d ",

                   3, 4, 5, maximum( 3, 4, 5 ) );

        System.out.printf( "%.1f, %.1f 和 %.1f 中最大的数为 %.1f ",

                   6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) );

        System.out.printf( "%s, %s 和 %s 中最大的数为 %s ","pear",

           "apple", "orange", maximum( "pear", "apple", "orange" ) );

     }

}

泛型类:

  如果我们需要在一个类中定义动态的属性的类型,则可以使用泛型类。

泛型类定义:

  在类名后接<类型变量1, 类型变量2, 类型变量3,..>

泛型类声明:

  类目<具体类型1,具体类型2,具体类型3,...>

示例:


public class Box<F> {
  private F f;

  public F getF() {
    return f;
  }

  public void setF(F f) {
    this.f = f;
  }
  public static void main(String[] args) {
    Box<Double> doubleBox = new Box<>();
    Box<Class> classBox = new Box<>();

    doubleBox.setF(3.1415926);
    classBox.setF(Class.class);
    System.out.printf("浮点数为:%f ", doubleBox.getF());
    System.out.printf("类为:%s ", classBox.getF());
  }
}


类型通配符: ?
用?代替具体的类型参数,代表允许传入任何类型的类型
public static void getData(List<?> data) {
  System.out.println("data :" + data.get(0));
}

类型通配符与不加通配符有何区别?
不加类型通配符的方法,在方法体里可对未限定类型进行任何数据类型的操作。
而加上类型通配符之后,因为不确定将传入何种类型,及被限定为“任意类型”的值,反而不能使用任意类型的数据进行操作。
如:
public static void getData(List data) {
  data.add(1);
}
是正确的。

public static void getData(List<?> data) {
  data.add(1);
}
会编译报错。
即使是
public static void getData(List<? extends Integer> data) {
  data.add(1);
}
也无法通过编译。


通配符上限: ? extends 上限类型
public static void getData(List<? extends Number> data) {
  System.out.println("data :" + data.get(0));
}
通配符下限: ? super Number
public static void getData(List<? super Number> data) {//表示只能接受Number及其父类类型
  System.out.println("data :" + data.get(0));

}  

皮皮鲁
原文地址:https://www.cnblogs.com/mizhifei/p/10863613.html