其一:写一个静态类,
Utiles.getObjFromJson() 在内部解析不同的类,返回的时候,返回一个Object就行。
其二:抽象成接口,
因为你有 items.add(new Notice(array.getJSONObject(i))) 估计有一些实体类都是需要解析的,那么 可以 抽象出来一个解析json的接口,items变成 ArrayList<JSONInterface> 这样的。
实现类继承抽象类并实现了所有抽象方法。但是,编译报错!!
报的是TopicListAdapter 类中没有实现onBindViewHolder方法,上面在抽象类中有一个泛型,这个泛型正好是抽象方法onBindViewHolder的第一个参数。这里TopicListAdapter 在继承时会继承BaseListAdapter中的内部类ViewHolder,也就是在TopicListAdapter 中也会有ViewHolder这个内部类,所以如果不指定是BaseListAdapter类中的ViewHolder则方法其实是这样定义的:
public void onBindViewHolder(TopicListAdapter.ViewHolder holder, int position) {}
很显然这不是抽象类中定义的方法(参数不一致),所以就造成无法覆盖!
ide没有没提示该错误!
Java的泛型是JDK5新引入的特性,为了向下兼容,虚拟机其实是不支持泛型,所以Java实现的是一种伪泛型机制,也就是说Java在编译期擦除了所有的泛型信息,这样Java就不需要产生新的类型到字节码,
所有的泛型类型最终都是一种原始类型,在Java运行时根本就不存在泛型信息。
使用ASM ByteCode Viewer查看他的字节码
可以看到我们设置的泛型R,被擦除为Object了,这就是泛型擦除
他的bytecode为
可以看到我们限定了泛型的类型,那么他的bytecode是什么样的?
可以看到虽然我们在Plate2中只定义了一个set get方法,但是bytecode中却有两个,其中一个get set方法添加了synthetic bridge 表示这是一个桥接方法,作用是为了保持多态性,可以看到 CHECKCAST java/lang/Comparable ,检查类型是否为Comparable,如果是的话再去调用上边的 public set(Ljava/lang/Comparable)V 方法。可以这样理解, set(Ljava/lang/Object)V 是从Plate接口实现来的, set(Ljava/lang/Comparable)V 是他本身的,因为限定了类型范围
上边我们是通过showbytecode的方式查看的字节码,但是如果你点开类生成的class文件,你会发现,泛型既然被擦除了为什么在class中仍然可以看到?其实这里看到的只是签名而已,还保留了定义的格式,这样对分析字节码有好处。你甚至可以通过javap -c Plate2.class反编译class,你会发现,R还是能被看到,我们要看bytecode,通过showbytecode的方式比较真实
比如没有ArrayList<int>,只有ArrayList<Integer>.当类型擦除后,ArrayList的原始类中的类型变量(T)替换成Object,但Object类型不能 存放int值
因为擦除后,ArrayList<String>只剩下原始类型,泛型信息String不存在了,所有没法使用instanceof
因为泛型类中的泛型参数的实例化是在定义泛型类型对象 (比如ArrayList<Integer>)的时候指定的,而静态成员是不需要使用对象来调用的,所有对象都没创建,如何确定这个泛型参数是什么
因为擦除后两个equals方法变成一样的了
因为类型不确定
因为数组是协变( 在某些情况下,即使某个对象不是数组的基类型,我们也可以把它赋值给数组元素。这种属性叫做协变(covariance) ),擦除后就没法满足数组协变的原则
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)