泛型的本质就是泛型参数化,确保类型一致性和安全性
泛型上限与泛型下限
泛型上限和泛型下限都是用于限定参数范围的
1.泛型上限(上限指的是上限范围,读取的上限范围,)
通过extends关键字来限制参数上限,通过限制操作的顶层基类,来控制读取的类型,因为你读取的所有的对象,都是这个顶层基类的子类,确保读取安全
2.泛型下限(下限指的是下限范围,写入的下限范围)
通过super关键字来限制参数下限,通过限制操作的顶层类型,来控制写入的类型,因为你写入的所有对象,都是这个类型顶层基类的子类,确保了写入安全
纠正我自己一个奇怪思想,这个大概率是因为平时没写代码导致的,根深蒂固的思想错误,我一度认为这是对的,但是发现编译不过去F是符类,S是子类
点击查看代码
public static void main(String[] args) throws Exception {
/* 泛型下限 */
List<? super S> list = new ArrayList<>();
F f = new F();
list.add(f); //编译错误
}
正确写法:明确存储的上限
点击查看代码
public static void main(String[] args) throws Exception {
/* 泛型下限 */
List<? super F> list = new ArrayList<>();
S s = new S();
list.add(s);
}
泛型中的桥接方法
前提:泛型中有泛型擦除的概念,泛型擦除是为了让泛型技术兼容JDK1.5之前的编译器,确保编译后没有泛型的总计,泛型会被具体的类型代理。
泛型桥接方法解决的问题:java中存在继承的关系,而桥接方法,解决了泛型擦除带来的多态性失效问题,下面举例子,假设我们存在如下泛型类以及子类
点击查看代码
class GenericClass<T> {
public T get(T t) {
return t;
}
}
class StringClass extends GenericClass<String> {
@Override
public String get(String s) {
return s;
}
}
泛型擦除后编译的代码
点击查看代码
class GenericClass {
public Object get(Object t) {
return t;
}
}
class StringClass extends GenericClass {
public String get(String s) {
return s;
}
// 桥接方法
@Override
public Object get(Object s) {
return get((String) s);
}
}