// 虽然还不是很清楚对应关系怎么做的,但至少常量池里有类型信息在里面
private Map map = new HashMap<>();
private Map map222 = new HashMap<>();
private List list = new ArrayList<>();
#20 = Utf8 map
#21 = Utf8 Ljava/util/Map;
#22 = Utf8 Signature
#23 = Utf8 Ljava/util/Map;
#24 = Utf8 map222
#25 = Utf8 Ljava/util/Map;
#26 = Utf8 list
#27 = Utf8 Ljava/util/List;
#28 = Utf8 Ljava/util/List;
证明擦除的例子
// 无法通过编译
public List test(List t) {
return new ArrayList<>();
}
public List test(List t) {
return new ArrayList<>();
}
桥方法是用来做什么的
继承了泛型类的类,里面的方法需要覆盖的时候用的
概念本质
伪泛型
编译期擦除类型变量,字节码中无泛型
类型推断
相同或仅一处,直接推断
不同,取最小公共父类型,直到Object
有返回值,以返回值确定
推断传递,即已存在明确的,如Vector
类型擦除 -> Object -> 类型推断 -> 强转进行类型替换
特点
类型参数不可继承,以下都会编译错误,下面阐述为什么错误
// 大转小
ArrayList list1 = new ArrayList
既然存在类型擦除,使用时又不需强转,那么隐式自动强转在哪实现?
JVM实现
源码实现,以ArrayList为例
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
@SuppressWarnings("unchecked")
E elementData(int index) {
return (E) elementData[index];
}
类型擦除与方法覆盖的矛盾
JVM如何在类型擦除的前提下,使得下面的Override生效
解决:桥方法
public class Pair {
private T value;
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
class DatePair extends Pair {
@Override
public Date getValue() {
return super.getValue();
}
@Override
public void setValue(Date value) {
super.setValue(value);
}
}
public java.lang.Object getValue();
descriptor: ()Ljava/lang/Object;
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokevirtual #6 // Method getValue:()Ljava/util/Date;
4: areturn
LineNumberTable:
line 14: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/fjh/test/genericity/DateInter;
public java.util.Date getValue();
descriptor: ()Ljava/util/Date;
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #2 // Method com/fjh/test/genericity/Pair.getValue:()Ljava/lang/Object;
4: checkcast #3 // class java/util/Date
7: areturn
LineNumberTable:
line 17: 0
LocalVariableTable:
Start Length Slot Name Signature
0 8 0 this Lcom/fjh/test/genericity/DateInter;
public void setValue(java.lang.Object);
descriptor: (Ljava/lang/Object;)V
flags: ACC_PUBLIC, ACC_BRIDGE, ACC_SYNTHETIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: checkcast #3 // class java/util/Date
5: invokevirtual #5 // Method setValue:(Ljava/util/Date;)V
8: return
LineNumberTable:
line 14: 0
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/fjh/test/genericity/DateInter;
public void setValue(java.util.Date);
descriptor: (Ljava/util/Date;)V
flags: ACC_PUBLIC
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: aload_1
2: invokespecial #4 // Method com/fjh/test/genericity/Pair.setValue:(Ljava/lang/Object;)V
5: return
LineNumberTable:
line 21: 0
line 22: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/fjh/test/genericity/DateInter;
0 6 1 value Ljava/util/Date;
字节码层面:允许返回值参与方法区分
注
// 桥方法是给p用的,而不是给dp用的;主要就是实现正确的覆盖
DatePair dp = new DateInter();
dp.set(new Date());
Pair p = dt;
p.set(new Date());
public static void copy(List super T> dest, List extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD || (src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i di=dest.listIterator();
ListIterator extends T> si=src.listIterator();
for (int i=0; i
用原型函数(prototype)可以定义一些很方便的自定义函数,实现各种自定义功能。本次主要是实现了Array的去重、获取最大值和最小值。
实现代码如下:
<script type="text/javascript">
Array.prototype.unique = function() {
var a = {};
var le
ORACLE
下面这个效率很低
SELECT * FROM ( SELECT A.*, ROWNUM RN FROM (SELECT * FROM IPAY_RCD_FS_RETURN order by id desc) A ) WHERE RN <20;
下面这个效率很高
SELECT A.*, ROWNUM RN FROM (SELECT * FROM IPAY_RCD_
Reverse a singly linked list.
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
p