对于初学者来说,我们可能会从各种渠道了解到一个关于泛型的官方解释 “Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。泛型的本质是参数化类型,即给类型指定一个参数,然后在使用时再指定此参数具体的值,那样这个类型就可以在使用时决定了。这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。” 问题来了,读完上面这句话你觉得自己知道什么是泛型了吗?
实际上,泛型,就是让类型泛化。比如说,不使用泛型的情况下,在定义一个ArrayList类型时,我们可以指定其add方法中接收某种特定类型的参数。但是,如果指定了add只接收特定类型参数,比如String类型,那这个ArraList类的数组对象,不就只能添加String类型的元素了吗?如果我们需要存放整型数那就需要另外定义一个存放整型数的ArrayList类,这么做显然降低了代码的重用性。所以,我们干脆在定义ArayList类型的时候就不指定add方法接收参数的具体类型,或者说什么类型的参数都可以接收,然后在使用的过程中,由用户根据需要指定传过来的是哪一种类型的参数。所以,用一句话来说,“泛型”就是允许一个类中的参数类型泛化。
这里举一个例子来说明:我们知道狗的食物类型很多,假设不同食物喂养的方式完全不一样,那么我们就需要定义不同的食物类型和各自的feed方法。对于dog类型来说,我们就不应该指定dog的食物类型,否则为了实现狗的食物对象获取方法,我们需要单独定义“吃菜狗”“吃肉狗”等类型。我们可以定义一个food接口,再定义vegetable和meat类实现,然后利用泛型实现dog类对象既能接收vegetable类型参数也能接收meat类型参数
定义food接口规范所有food必须实现feed方法:
public interface Food {
public void feed();
}
实现Vegetable类(用print语句代替业务逻辑):
public class Vegetable implements Food {
public void feed(){
System.out.println("吃青菜:\n把青菜扔进锅里煮五分钟捞出\n放上少许酱油\n把青菜放进餐盘\n开始食用\n\n");
}
}
实现Meat类:
public class Meat implements Food {
public void feed(){
System.out.println("吃肉:\n把肉从冰箱取出\n切成小块\n大火爆炒\n装盘\n开始食用\n\n");
}
}
定义dog类 :
public class Dog<T> {//泛型的使用,<T>表示这是一个泛型类,T代表一种类型,但这个类型需要用户指定
private T food;
public T getFood() {
return food;
}
public void setFood(T food) {
this.food = food;
}
}
这个dog类就是对泛型的使用,<T>表示这是一个泛型类,这个T将在定义对象时被指定,指定后,该对象中的T则被所指定的类型代替。这里的标识使用什么字母都可以,但一般T标识type,用E表示element,用K表示key,用V表示value。
主方法:
public class Test {
public static void main(String args[]){
Dog<Vegetable> dog1 =new Dog<>();//指定T为Vegetable
Vegetable v=new Vegetable();
dog1.setFood(v);//原方法setFood(T food)经过指定相当于setFood(Vegetable food)
dog1.getFood().feed();
Dog<Meat> dog2 =new Dog<>();//指定T为Meat
Meat m=new Meat();
dog2.setFood(m);//原方法setFood(T food)经过指定相当于setFood(Meat food)
dog2.getFood().feed();
}
}
上述方法中,通过<具体类型>指定dog1和dog2对象中“T”的具体类型
回头看“泛型”二字,泛型更强调的是“类中的定义很泛化”,泛型类的泛型标识T可以表示任何类,这个T可以在类的定义中泛化地表示一个未被确定的类型,用这个未被指定的类型来定义私有属性或者方法接收参数类型等等。但是,当泛型类定义具体对象时,这个对象就并不“泛”了。如dog2.setFood(v)是一个错误写法,dog2对象已经指定其T为Meat而不是Vegetable。
泛型接口和泛型类的使用差不多,也是用泛型标识标识未指定的类,作为定义接口方法的返回类型或参数等。
泛型接口定义格式为:
interface fortest <T> {
T test();
}
实现泛型接口格式为:
public class demo1 implements fortest <String> {
public String test(){
return "hello";
}
}