今天又重新看了一遍泛型,总结下
1 首先 object 这个对象之父,而泛型之中对象t就是以object存在的,
class test<T>{private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return ("tttis "+t);
}
public void listTest(){
}
public static void main(String[] args) {
test<String> t=new test<String>();//1
t.setT("looooo");
System.out.println("t1:"+t);
test<Integer> t2=new test<Integer>();//2
t2.setT(11);
System.out.println("t2t2 "+t2.toString());
}
T 可以根据具体需求变成相应的对象、、
2 经典的list 泛型实例
List <String > list=new ArrayList<String >(); 这样list 中就只能接受String 类型的list了。
解决了 list 的强转问题 ,以及list.add安全的问题
3.泛型接口
interface int1<T>{
void say(){
}
4.泛型通配符的使用
- void printList(List<?> l) {
- for (Object o : l)
- System.out.println(o);
- }
- 这样 o可以认同。
-
- void printList(List<String> l) {
- for (Object o : l) //报错
- System.out.println(o);
- }
-
-
- 5
-
- List<Integer> li = new ArrayList<Integer>();
- li.add(new Integer(42));
- List<?> lu = li;
- lu.add(new Integer(43)); // error
以免您仍然认为编译器知道哪些方法更改列表的内容哪些不更改列表内容,请注意下面的代码将能工作,因为它不依赖于编译器必须知道关于 lu 的类型参数的任何信息:
-
-
6
-
- public class Matrix<V extends Number> { ... }
编译器允许您创建 Matrix<Integer> 或 Matrix<Float> 类型的变量,但是如果您试图定义 Matrix<String> 类型的变量,则会出现错误。类型参数 V 被判断为由 Number 限制 。在没有类型限制时,假设类型参数由 Object 限制。这就是为什么前一屏 泛型方法 中的例子,允许 List.get() 在 List<?> 上调用时返回 Object,即使编译器不知道类型参数 V 的类型。
泛型底层细节
擦除
也许泛型最具挑战性的方面是擦除(erasure),这是 Java 语言中泛型实现的底层技术。擦除 意味着编译器在生成类文件时基本上会抛开参数化类的大量类型信息。编译器用它的强制类型转换生成代码,就像程序员在泛型出现之前手工所做的一样。区别在于,编译器开始已经验证了大量如果没有泛型就不会验证的类型安全约束。
尽管不能将 ArrayList<Integer> 赋给 ArrayList<Number>,因为它们不是协变的,但是 ArrayList<Integer> 和 ArrayList<Number> 类型的变量是相同的类!请评价下面的代码:
-
编译器只为 ArrayList生成一个类。当生成了 ArrayList的字节码时,将很少剩下其类型参数的跟踪。
当生成泛型类的字节码时,编译器用类型参数的 擦除 替换类型参数。对于无限制类型参数(<V>),它的擦除是 Object。对于上限类型参数(<K extends Comparable<K>>),它的擦除是其上限(在本例中是 Comparable)的擦除。对于具有多个限制的类型参数,使用其最左限制的擦除。如果检查生成的字节码,无法说出 List<Integer> 和 List<String> 的代码之间的区别。类型限制 T 在字节码中被 T 的上限所取代,该上限一般是 Object。
擦除的含意
擦除有很多初看起来似乎奇怪的含意。例如,因为类只可以实现一个接口一次,所以不能像下面这样定义类:
由于擦除,上面的声明没有意义。Comparable 的两个实例化是同一个接口,不能实现一个方法或接口两次。擦除的另一个更加烦人的含意是,不能使用类型参数实例化一个对象或数组。这意味着您不能在带有类型参数 T 的泛型类中使用 new T() 或 new T[10]。因为编译器只是不知道生成什么样的字节码。
- public void remove(V value) {
- int removalCount = 0;
- for (int i=0; i<size; i++) {
- if (array[i].equals(value))
- ++removalCount;
- else if (removalCount > 0) {
- array[i-removalCount] = array[i];
- array[i] = null;
- }
- }