bls java_JAVA泛型与类型安全

1. 基础泛型//定义泛型类,接口的定义和类一样class A {

T t;

P p;// extends 限定泛型上界

public  M doSomething(M params) {}

}

关于泛型的使用基本如此,开发者可以在实际使用时灵活地指定泛型所对应的实际类型,从而达到不同的效果

2. 协变与逆变与不变协变

在Java中的数组是协变的,简单来说即有:A extends B  ==>  A[] extends B[]

B[] bs = new A[2]; //合法逆变

与协变相对,逆转了类型关系不变Java 语言中的泛型基本上完全在编译器中实现,由编译器执行类型检查和类型推断,然后生成普通的非泛型的字节码。这种实现技术称为擦除(erasure)(编译器使用泛型类型信息保证类型安全,在生成字节码之前将其清除,替换为非泛型上界)

由于泛型擦除的原因,Java中的泛型是不变的,因此在使用泛型的地方(比如集合)中List bls = new ArrayList();//不合法

编译器检查不通过,我们假设B可以有其它的子类比如C,由于bls的引用指定的类型是B,所以C extends B

bls.add(new C())

显然应该是合法的,但事实上bls指向的实例指定的类型是A,而A与C并没有直接继承关系,这就导致类型异常的问题。但是显然问题不能就这样结束,因此为了解决泛型的不变,就需要用到通配符?与extends、super。

3. 通配符? 与 extends 与 super

先以泛型集合List为例来说明以上三个关键字的特性

(1)通配符?在单独使用时可以看作是? extends ObjectList> l0= new ArrayList();

(2)? extends xxx使得泛型具有协变的特性,extends限定了泛型的上界//extends包含指向类及其子类List extends Number> l1= new ArrayList();List extends Number> l2= new ArrayList();l1.add(new Integer(1));//无法编译Number n = l1.get(0);//可以获取到

当向l1中add一个元素,不管是任何类型的元素,都是不合法的,因为泛型下界无法确定,比如Integer和Double同是Number的子类,但是一个指向List的实例add一个Double类型的元素显然是不合法的;当从l1中get一个元素,泛型上界确定是Number

(3)? super xxx使得泛型具有逆变的特性,super限定了泛型的下界//super包含指向类及其父类List super Integer> l3 = new ArrayList();List super Integer> l4 = new ArrayList();l3.add(new Integer(1));//可以编译Object o = l3.get(0);//可以获取到

想要向l3中add一个元素,泛型下界确认为Integer,那么这个元素必须是Integer及其子类的类型;当从l3中get一个元素时,由于JAVA中所有类型总是Object的子类,所以泛型上界可以确定是Object

总结一点就是:写入需要有类型下界,而读出需要有类型上界

在Android中,一个典型的例子就是RxJava的map操作public final  Observable map(Function super T, ? extends R> mapper) {

ObjectHelper.requireNonNull(mapper, "mapper is null");    return RxJavaPlugins.onAssembly(new ObservableMap(this, mapper));

}public interface Function {    /**

* Apply some calculation to the input value and return some other value.

* @param t the input value

* @return the output value

* @throws Exception on error

*/

R apply(@NonNull T t) throws Exception;

}

作者:白与兰与白兰地

链接:https://www.jianshu.com/p/43beda48c665

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值