java中泛型知识点解析和总结

一、泛型基础

(1)泛型类

我们首先定义一个简单的Box类:

public class Box {    
private String object;   
public void set(String object) { 
    this.object = object; 
    }    
public String get() { 
    return object; 
    }
}

这是最常见的做法,这样做的一个坏处是Box里面现在只能装入String类型的元素,今后如果我们需要装入Integer等其他类型的元素,还必须要另外重写一个Box,代码得不到复用,使用泛型可以很好的解决这个问题。

public class Box<T> {    // T stands for "Type"
    private T t;   
    public void set(T t) {
    this.t = t;
  }    
  public T get() { 
    }
}

这样我们的Box类便可以得到复用,我们可以将T替换成任何我们想要的类型:

Box<Integer> integerBox = new Box<Integer>();
Box<Double> doubleBox = new Box<Double>();
Box<String> stringBox = new Box<String>();

(2)泛型方法

看完了泛型类,接下来我们来了解一下泛型方法。声明一个泛型方法很简单,只要在返回类型前面加上一个类似
“< K,V >”的形式就行了:

public class Util {    
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {       
 return p1.getKey().equals(p2.getKey()) &&p1.getValue().equals(p2.getValue());
    }
}
public class Pair<K, V> {    
private K key;    
private V value;    
public Pair(K key, V value) {        
this.key = key;        
this.value = value;
    }    
public void setKey(K key) { 
this.key = key; 
}    
public void setValue(V value) { 
this.value = value; 
}    
public K getKey()   { 
return key; 
}   
 public V getValue() { 
 return value; 
 }
}

我们可以像下面这样去调用泛型方法:

Pair<Integer, String> p1 = new Pair<>(1, "apple");
Pair<Integer, String> p2 = new Pair<>(2, "pear");
boolean same = Util.<Integer, String>compare(p1, p2);

类型擦除

1、什么是类型擦除:

类型擦除就是说Java泛型只能用于在编译期间的静态类型检查,然后编译器生成的代码会擦除相应的类型信息,这样到了运行期间实际上JVM根本就知道泛型所代表的具体类型。这样做的目的是因为Java泛型是1.5之后才被引入的,为了保持向下的兼容性,所以只能做类型擦除来兼容以前的非泛型代码。对于这一点,如果阅读Java集合框架的源码,可以发现有些类其实并不支持泛型。

说了这么多,那么泛型擦除到底是什么意思呢?我们先来看一下下面这个简单的例子:

public class Node<T> {   
private T data;    
public Node(T data, Node<T> next) {   
this.data = data;        
this.next = next;
    }   
 public T getData() { 
 return data;
}    
// ...}

编译器做完相应的类型检查之后,实际上到了运行期间上面这段代码实际上将转换成:

public class Node {    
private Object data;    
private Node next;   
public Node(Object data, Node next) { 
this.data = data;        
this.next = next;
   }    
public Object getData() { 
 return data; 
 }    
 // ...
 }

这意味着不管我们声明Node还是Node,到了运行期间,JVM统统视为Node。有没有什么办法可以解决这个问题呢?这就需要我们自己重新设置bounds了,将上面的代码修改成下面这样:

public class Node<T extends Comparable<T>> {    
private T data;    
private Node<T> next;    
public Node(T data, Node<T> next) {        
this.data = data;        
this.next = next;
    }    
public T getData() {
 return data; 
 }    // ...
 }

这样编译器就会将T出现的地方替换成Comparable而不再是默认的Object了:

public class Node {    
private Comparable data;   
private Node next;    
public Node(Comparable data, Node next) {        
this.data = data;        
this.next = next;
    }    
public Comparable getData() { 
return data; 
}    // ...
}

猜你喜欢

转载自blog.csdn.net/qq_41112517/article/details/80206384