Java泛型
在JDK1.4以前类型不明确:
- 装入集合的类型都被当做Object对待,从而失去自己的实际类型
- 从集合取出时往往需要转型,效率低,容易产生错误
泛型的作用:
- 模板:提高代码的重用率
- 安全:在编译时检查类型安全
- 省心:所有的强制转换都是自动和隐式的
泛型类
泛型类:
- 定义时使用泛型
<>
定义模板如下:
public class 类名<字母> {
}
注意:
- 泛型指定的类型不能是基本类型
- 泛型不能使用在静态属性上
private static T a;//编译错误
泛型字母
泛型字母可以随意指定,尽量使用单个大写字母(有时多个泛型类型会加上数字,如T1、T2)
常见字母:
- T Type
- K V Key Value
- E Element
泛型接口
泛型接口实例:
public interface Comparator<T> {
public static final int MAX_VALUE = 1024;
void compare(T t);
}
注意:接口中泛型字母只能使用在方法中,不能使用在全局常量中
泛型方法
泛型方法是在定义方法是,在返回类型前面写一个<X>
public class Method {
public static <T> void test(T t){
System.out.println(t);
}
public static <T extends List> void test(T t){
System.out.println(t);
t.add("ttt");
}
public static void main(String[] args) {
test("Hello");
}
}
或者如下的形式:
public static <T extends Closeable> void test(T... t){
for (T temp : t) {
try {
if (null != temp) {
temp.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Closeable
中有一个close
方法...
表示可变参数
泛型继承
父类为泛型,子类继承时,如下的父类:
public abstract class Father<T1, T2> {
}
1.子类保留泛型
子类保留父类的泛型,子类为泛型类
a.子类全部保留
class C1<T1,T2> extends Father<Integer, T2>{}
b.子类部分保留
如果我们这么写:
class C2 extends Father<Integer, T2>{}
编译其会提示错误:T2 cannot resolved to a type
所以要改成如下的形式:
class C2<T2> extends Father<Integer, T2>{}
2.子类不保留泛型
子类不保留父类泛型,子类按实际需求实现,可以是泛型类,也可以不是泛型类
a.子类指定具体类型
class C3 extends Father<Integer, String>{
}
b.子类没有指定类型
如下:
class C4 extends Father{
}
等同于
class C4 extends Father<Object, Object>{
}
泛型接口与泛型类同理
public interface Comparator<T> {
}
class interC1<A> implements Comparator {}
class interC2<A> implements Comparator<Integer> {}
class interC3<T, A> implements Comparator<T> {}
泛型擦除
泛型擦除是指在继承(实现)或使用时没有指定具体的类型,把它当做Object
来处理
通配符
通配符?
,表示未知类型,类型参数赋予不确定值,任意类型
其只能用在声明类型、方法参数上,不能用在定义泛型类上
public class WildcardsTest {
public static void main(String[] args) {
List<?> list = new ArrayList<Integer>();
list = new ArrayList<Object>();
list = new ArrayList<String>();
}
public static void test(List<?> list){
}
}
上限
上限extends
指定类型必须是继承某个类,或者实现某个接口
下限
下限super
指定的类型不能小于操作的类
T super Apple
? super Apple