希望弄懂:

一. 泛型的好处

二. 表述

三. <R extends T>的作用

四. <? super T>,<? extends T>作为参数类型的作用

五. wildcard嵌套 <? extends|super ? extends|super T>

 

一. JDK1.5 引入了泛型,好处:

1. 编译时,类型检查

2. 避免类型转换

 

例如,

java泛型的类型传递 java泛型的?_参数类型

java泛型的类型传递 java泛型的?_泛型_02

ArrayList list = new ArrayList();
list.add("str1")
System.out.prinntln((String)list.get(0)).length());

JDK1.4的写法

缺陷:

1. 没有类型保证,如果list.add(new Object()); 那么(String)list.get(0); 就会ClassCastException

2. 没有使用list中的元素都要强制转换

 

在使用泛型,就方便多了

java泛型的类型传递 java泛型的?_参数类型

java泛型的类型传递 java泛型的?_泛型_02

ArrayList<String> list = new ArrayList<String>();
list.add("str1");
System.out.println(list.get(0).length());

JDK1.5写法

对于JDK1.7或以上,还进一步简化:

java泛型的类型传递 java泛型的?_参数类型

java泛型的类型传递 java泛型的?_泛型_02

ArrayList<String> list = new ArrayList<>();

JDK1.7写法

 后面会自动添加类型;

 

二. 几种表述:

1. 泛型静态函数

public class C {
  public static <T> T foo(T v) {
    return null;
  }
}
//用法:
String ret = C.foo("str");

 2. 泛型类

public class C<T> {
  public T foo(T v) {
    return null;
  }
}
//用法:
C<String> instance = new C<String>();
String ret = instance.foo("str");

3. 泛型成员函数

public class C {
  public <T> T foo(T v) {
    return null;
  }
}
//用法:
C instance = new C();
String ret = instance.foo("str");

 4. 泛型类的泛型成员函数

public class C<R> {
  public <T> T foo(T v1, R v2) {
    return null;
  }
}
//用法:
C<String> instance = new C<String>();
Integer ret = instance.foo(1, "str");

5. 泛型类的泛型静态函数

public class C<R> {
  public static <T> T foo(T v1) {
    return null;
  }
}
// (R的泛型没意义)
Integer ret = C.foo(1);

6. public class C<T> { public static T foo(T v) {return null;} } 不能编译

 

 

三. ,<R extends T>的作用

作为方法的类型,

extends提供R的上限,如<R extends Number>,R可以是Number,Integer,Double等继承Numberl类,起到限制作用。

没有<R super T>,如<R super Number>,R可以是Number, Serializable,由于子类都可以放到父类上,相当于Number,所以没意义

public class C {
  public static <R extends Number> T foo(R v) {
    return v;
  }
}
Integer ret = C.foo(1);

作为类的类型,也是类似的

public class C<R extends Number> {
  public R foo(R v) {
    return v;
  }
}
C<Integer> instance = new C<Integer>();
Integer ret = instance.bar(1);

那么,采用<R extends Number>的好处有哪些呢:

1. v能知道是Number或子类,能提早使用Number的方法,v.intValue();

2. 现在具体化的范围,如C<String>编译错误

 

至于class C<R super Number> 同样不支持。

 

四. <? super T>,<? extends T>作为参数类型的作用

先说一下,泛型删除

<?>代表没类型,如果作为参数类型,就只能接收null值;如果作为返回类型,就只能返回Object;一般这类,只能用没有泛型的函数,或者说,不关心其类型

public class C<T> {
  public T foo(T v) {
    return v;
  }
  public String bar(int i) {
    return "" + i;
  }
}
 
C<?> instance = new C<?>();
Object ret = instance.foo(null); // 这个用法没实际作用
String sRet = instance.bar(1); // 主要调用没有类型部分

既然C<?>不用考虑T的类型,那么具体化也可以,如 C<?> instance = new C<String>();

这样设计,创建者能根据自己需要设置类型,而使用者就不用关系类型

如果需要使用数据类型,就可以使用

C<? super Number> 或 C<? extends Number>

C<? super Number> 适合传入类型,返回没类型,容器能向下兼容

C<? super Number> instance = new C<Object>();
Object ret = instance.foo(new Integer(0)); // 接受Number的参数;但返回值Object,一般用于,修改数据。

C<? extends Number> 适合返回类型,而且不能传入参数,容器能向上兼容

C<? extends Number> instance = new C<Integer>();
Number ret = instance.foo(null); // 不接收参数,但返回Number,一般用于,获取数据。

 

五. wildcard嵌套 <? extends|super ? extends|super T>

这部分其实没什么意义,可以看成<? super T>和<? extends T>,仅仅为了语言的完整性

以下用例子说明:

java泛型的类型传递 java泛型的?_参数类型

java泛型的类型传递 java泛型的?_泛型_02

public class C<T> {
  public C<? super T> foo(C<? super T> v) {
    return v;
  }
  public C<? extends T> bar(C<? extends T> v) {
    return v;
  }
}
 
C<? super Number> s = null;
C<? extends Number> e = null;
 
C<? super Number> sInstance = new C<Object>();
C<? super Number> ret1 = sInstance.foo(null);
C<?> ret2 = sInstance.bar(e);
 
C<? extends Number> eInstance = new C<Integer>();
C<?> ret3 = eInstance.foo(s);
C<? extends Number> ret4 = eInstance.bar(null);

View Code

归纳如下:

<? super ? super T> 参数类型:null,返回值<? super T>

<? extends ? super T> 参数类型:<? extends T>,返回值<?>

<? super ? extends T> 参数类型<? super T>,返回值<?>

<? extends ? extends T> 参数类型为null, 返回值<? extends T>