多态:可以将方法的参数类型设为基类,那么这个方法就可以接受从这个基类中导出的任何类作为参数。
泛型:实现了参数化类型的概念,代码可以应用于多种类型。泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。
参数化类型:类似定义方法时有形参,然后调用此方法时传递实参。那么参数化类型就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
类型参数:用尖括号括住,放在类名后面,在使用类的时候,用实际的类型替换此类型参数。
//一个只能持有单个对象的类
class Automobile{}
public class Holder {
private Automobile a;
public Holder(Automobile a) {
this.a = a;
}
Automobile get(){
return a;
}
}
//持有Object可以持有多种类
class Automobile{}
public class Holder {
private Object a;
public Holder(Object a) {this.a = a;}
public void set(Object a) {this.a = a;}
public Object get() {return a;}
public static void main(String[] args) {
Holder h = new Holder(new Automobile());
Automobile a = (Automobile)h.get();
h.set("hello world");
String s = (String) h.get();
h.set(1);
Integer x = (Integer)h.get();
}
}
//泛型
class Automobile{}
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<Automobile> h = new Holder<Automobile>(new Automobile());
Automobile a = h.get();
}
}
当创建对象的时候,必须指明想持有什么类型的对象。核心概念,告诉编译器想使用什么类型,编译器处理一切细节。
元组(数据传送对象):将一组对象直接打包存储于其中的一个单一对象,这个容器对象允许读取其中元素,但不允许向其中存放新的对象。
public class Holder<A,B> {
public final A aa;
public final B bb;
public Holder(A a, B b) {
aa = a;
bb = b;
}
public String toString() {
return "("+aa+","+bb+")";
}
}
一个持有特定类型的列表,每次调用select()方法,就返回随机一个元素。
public class RandomList<T>{
private ArrayList<T> storage = new ArrayList<T>();
private Random rand = new Random(47);
//添加
public void add(T item){
storage.add(item);
}
//查找方法
public T select(){
return storage.get(rand.nextInt(storage.size()));
}
public static void main(String[] args){
RandomList<String> rs = new RandomList<String>();
for(String s : ("hello world").split())
rs.add(s);
for(int i = 0; i<11; i++)
System.out.println(rs.select());
}
}
泛型接口:泛型也可以用于接口,例如生成器,这是一种专门负责创建对象的类。使用生成器创建新的对象时,不需要任何参数。
public interface Generator<T> {T next();}
public class Test implements Generator<Integer>{
private int count = 0;
public Integer next(){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){
Test test = new Test();
for(int i =0;i<18;i++){
System.out.println(test.next());
}
}
}
泛型方法:可以在类中包含参数化方法。static方法无法访问泛型类的类型参数。应该尽可能使用泛型方法。
定义泛型方法,只需将泛型参数列表置于返回值之前。
public class Test {
public <T> void f(T a){
System.out.println(x.getClass.getName);
}
public static void main(){
Test test = new Test();
test.f("");
test.f(1);
}
}
java.lang.String
java.lang.Integer
使用泛型方法不必指明参数类型,编译器会为我们找出具体类型。