泛型:实现了参数化的概念,使代码可以运用与多种类型。
泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器保证类型的正确性。
public class Holder<T> {
private T a;
public Holder(T a) {
this.a=a;
}
public void set(T a) {
this.a=a;
}
public T get() {
return a;
}
public static void main(String[] args) {
Holder<String> h=new Holder<String>("string");
String b=h.get();
//h.set(1); 通不过编译器
}
}
概念:它是将一组对象直接打包存储于其中一个单一对象,这个容器对象允许读取其中元素,但不允许向其中存放新的对象。
public class TwoTuple<A,B> {
public final A first;//创建之后不能再创建
public final B second;
public TwoTuple(A a,B b) {
first=a;
second=b;
}
@Override
public String toString() {
return "TwoTuple [first=" + first + ", second=" + second + "]";
}
}
用继承增加长度
class ThreeTuple<A,B,C> extends TwoTuple<A,B>{
public final C third;
public ThreeTuple(A a,B b,C c) {
super(a,b);
this.third=c;
}
}
泛型可以应用于接口,例如生成器,这是一种专门负责创建对象的类
public interface Generator<T>{T next();}
接口的实现
public class Fibonacci implements Generator<Integer>{
private int count=0;
@Override
public Integer next() {
// TODO Auto-generated method stub
return fib(count++);
}
private int fib(int n) {
if(n<2) return 1;
return fib(n-2)+fib(n-1);//递归
}
public static void main(String[] args) {
Fibonacci gen=new Fibonacci();
for(int i=0;i<10;i++) {
System.out.print(gen.next()+" ");
}
}
}
要定义与使用泛型方法只需将参数列表置于返回值之前
public class GenericMethod {
public <T>void f(T x){
System.out.println(x.getClass().getSimpleName());
}
public static void main(String[] args) {
GenericMethod gm=new GenericMethod();
gm.f("");
gm.f(1);
gm.f(1.0);
gm.f(1.0f);
gm.f(gm);
}
}
import java.util.*;
//
public class GeneriVarargs {
public static <T> List<T> makelist(T... args){
List<T> result=new ArrayList<T>();
for(T item:args) {
result.add(item);
}
return result;
}
public static void main(String[] args) {
List<String> is=makelist("A");
System.out.println(is);
is=makelist("A","B","C");
System.out.println(is);
is=makelist("ABCDEFGHIJKLMN".split(""));
System.out.println(is);
}
}
擦除
import java.util.*;
//
class Frob{};
class Fnorkle{};
class Quark<Q>{};
class Particle<M,N>{};
//
public class LostInformation {
public static void main(String[] args) {
List<Frob> list=new ArrayList<Frob>();
Map<Frob,Fnorkle> map=new HashMap<>();
Quark<Fnorkle> quark=new Quark<Fnorkle>();
Particle<Long,Double> p=new Particle<>();
//
System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
System.out.println(Arrays.toString(p.getClass().getTypeParameters()));
}
}
Class.getTypeParameters()将返回一个TypeVariable对象的数组,表示所声明的类型参数。
输出:
因此在泛型代码的内部,无法获得任何有关泛型的参数类型信息。
所以当再使用泛型时,任何具体的类型信息都会被擦除,List<“String”>与List<“Integer”>都会被擦除成为他们的原生类型,即List。
import java.util.*;
//
public class ErasedTypeEquivalence {
public static void main(String[] args) {
Class c1 = new ArrayList<String>().getClass();
Class c2 = new ArrayList<Integer>().getClass();
System.out.println(c1 == c2);
}
} /* Output:
true
*///:~