最近在帝都好无聊啊, 排遣寂寞就只有让自己不要停下来,不断的思考了 QWQ;

最近做ndk, java有点忘了,突然看到了一些java范型方面的问题, 踌躇了一会, 想着想着,决定还是写个随笔记录下来。

范型语法这个网上找度娘可以要到一大把, 我就不记了, 主要是范型上下限问题。

案例:

public class Test {

  public static class Base{

  }

  public static class A extends Base{

  }

  public static class Fanxin<T>{

  T t;

  public T get(){

  return t;

  };

  public void set(T t){

  this.t = t;

  }

}

public static class B extends A{

}

  public static void main(String[] arvg){

    Fanxin<? extends Base> fanxin = new Fanxin<A>();

    Base a = fanxin.get();

    //fanxin.set(new A()); 1编译报错

    Fanxin<? super A> fanxin1 = new Fanxin<Base>();

    A obj = (A)fanxin1.get();

    //A obj = fanxin1.get(); 2编译报错

    //fanxin1.set(new Base());3编译报错

    fanxin1.set(new A());

  }

}

首先java范型我理解的是为了安全, 这样可以在编译期检测类型,而不会到运行的时候出现类型转化异常。 第一个 fanxin.set(new A());报错,是因为,这里类型是定义了上限,所以这里通配符代表的类型是base或者base的子类, 虽然A是base的子类, 但是这是不安全的,考虑这种情况:

Fanxin<B> fanxin = new Fainxin<B>();

......各种操作......

Fanxin<? extends Base> fanxin1 = fanxinB;

fanxin1.set(new A());

B b = fanxin.get();//这里有问题

这时候不安全的因素发生了,我们对fanxin1设置了一个对象A, 但是fanxin1实质是fanxin<B>对象, 这时候如果我们fanxin.get()获得的实际上是A对象,运行的时候会有类型转化异常。

这样是不安全的, 所以编译的时候会报错,如果一定要set, 那么可以强制类型转换来做,但是这样也失去了意义:

Fanxin<A> fanxinA = (Fanxin<A>)fanxin1;

fanxinA.set(new A());

第二个问题,通配符是A或者A的父类, 所以我们可以赋值, 面向对象的原则是子类可以替代父类, 所以是安全的。 但是如果我们读区值,然后赋值给其他对象,那么就会有问题, 比如;

Fanxin<Base> fanxinBase = new Fanxin<Base>();

Fanxin<? super A> fanxin1 = fanxinBase;   //Fanxin<? super A> fanxin = new Fanxin<? super A>();编译报错

A a =  fanxin1.get();

这里fanxin1.get()实际获得的是Base类, 赋值给A类,编译会报错, 运行的时候会有类型转化异常。

当然如果我们知道这个类的类型,那么我们也可以用强制类型转换避免编译报错。

例:

Base b = (Base) fanxin1.get();

总之 ?是范型里面的通配符,extends, super只是提供上下限的信息给编译起, 通配符有集合的概念在里面,Fanxin< ? extends Base>, ?类型可能是Base的任何子类,所以我们不能有赋值操作,因为子类和子类是不同的类型,只是子类可以替换父类而已,所以可以按父类来读取值, Fanxin<? super A>, ?类型是A的超类, 所以我们可以将A的任何子类赋值给他,这样是安全的,但是读取的时候,是无法知道这是什么类型的,但是java类都是Object类的扩展, 所以可以获取值赋给obj对象, Object obj = fanxin.get(); 如果要赋值给其他对象那么只有强制类型转换了。

最新文章

  1. JAVA的i++, i+=1, i=i+1有区别吗?
  2. 【unity3d游戏开发脚本笔记之一:坐标系选择对物体运动的影响】
  3. c# mybatis net +mysql
  4. QQ提醒的功能
  5. 词法分析器Demo
  6. 内存对齐-C语言struct内存占用问题
  7. iOS的崩溃和编译错误
  8. 让Eclipse使用新版本的JRE
  9. Android开发--UI之Bundle的使用
  10. oracle 表查询(1)
  11. java在的数据类型
  12. Kafka的基本概念与安装指南(单机+集群同步)
  13. Jmeter-使用Stepping Thread Group插件来设置负载场景
  14. 【黑客免杀攻防】读书笔记10 - switch-case分支
  15. Linux的缓存内存 Cache Memory详解
  16. 爬虫6:pyquery库
  17. python学习整理
  18. Selenium基础知识(8大元素定位概说)
  19. zabbix经常报警elasticsearch节点TCP连接数过高问题
  20. webSQL 实现即时通讯

热门文章

  1. Struts2对Ognl的支持
  2. Blackfin DSP(八):BF533的DMA
  3. angularjs实现 checkbox全选、反选的思考
  4. sql条件中比较性能优化
  5. 小杨同学git使用记(适合使用过git但是不熟练的童鞋)
  6. Cacti客户端SNMP的安装和配置
  7. SQL SELECT语句
  8. checkbox绿色圆圈样式
  9. CSS声明顺序
  10. css 透明(transparent)