1、泛型概述
- 在Java中增加泛型之前,泛型程序设计是使用继承来实现的。这样做的坏处有:
- 需要强制转换。
- 可以向集合中添加任意类型的对象,存在风险。
- Java SE7及以后的版本中,构造方法中可以省略泛型类型,如:
List<String> list=new ArrayList<>();
- 多态与泛型:例如子类Cat继承了父类Animal,那么
List<Animal> list=new ArrayList<Cat>();
这种写法是错误
的,变量声明的类型必须匹配传递给实际对象的类型,即前后类型必须一致。
2、泛型作为方法参数
- 1.新建一个名为
GenericProj
的Java项目,新建一个com.cxs.generic
的包,在包下依次建立Goods
、Books
、Clothes
、Shoes
及GoodsSeller
类,具体代码如下:
public abstract class Goods {
public abstract void sell();
}
public class Books extends Goods {
@Override
public void sell() {
System.out.println("Sell books!");
}
}
public class Clothes extends Goods {
@Override
public void sell() {
System.out.println("Sell clothes!");
}
}
public class Shoes extends Goods {
@Override
public void sell() {
System.out.println("Sell shoes!");
}
}
public class GoodsSeller {
public void sellGoods(List<Goods> goodsList) {
for (Goods good : goodsList) {
good.sell();
}
}
}
- 2.在
generic
包下新建一个测试类GoodsTest
。
public class GoodsTest {
public static void main(String[] args) {
List<Books> booksList = new ArrayList<>();
booksList.add(new Books());
booksList.add(new Books());
List<Clothes> clothesList = new ArrayList<>();
clothesList.add(new Clothes());
clothesList.add(new Clothes());
List<Shoes> shoesList = new ArrayList<>();
shoesList.add(new Shoes());
shoesList.add(new Shoes());
GoodsSeller goodsSeller = new GoodsSeller();
goodsSeller.sellGoods(booksList);
goodsSeller.sellGoods(clothesList);
goodsSeller.sellGoods(shoesList);
}
}
- 3.此时测试类sellGoods方法处会报错,显然传入的参数不正确,我们在
GoodsSeller
类中的sellGoods(List<Goods> goodsList)
方法所传参数的泛型限定为Goods类型,因此传入Books会报错。 - 4.修改sellGoods方法,如下所示。
public class GoodsSeller {
public void sellGoods(List<? extends Goods> goodsList) {//←——修改参数的泛型
for (Goods good : goodsList) {
good.sell();
}
}
}
注:上面的泛型若改为
sellGoods(List<? super Goods> goodsList)
则将类型限定为Goods及其超类。
- 5.这时,错误消失,运行代码,结果如下。
3、自定义泛型类
- 1.新建一个NumGeneric的类,并勾选主方法。
public class NumGeneric<T> {// T代表不确定类型,相当于一个占位符
private T num;
public T getNum() {
return num;
}
public void setNum(T num) {
this.num = num;
}
// 测试
public static void main(String[] args) {
NumGeneric<Integer> intNum = new NumGeneric<>();
intNum.setNum(10);
System.out.println("泛型为Integer:" + intNum.getNum());
NumGeneric<Float> floatNum = new NumGeneric<>();
floatNum.setNum(10.0f);
System.out.println("泛型为Float:" + floatNum.getNum());
}
}
- 2.运行代码结果如下。
- 3.再来演示一个例子,新建一个TwoNumGeneric类,代码如下:
public class TwoNumGeneric<T, X> {
private T num1;
private X num2;
public TwoNumGeneric() {
}
public void genericNum(T num1, X num2) {
this.num1 = num1;
this.num2 = num2;
}
public T getNum1() {
return num1;
}
public void setNum1(T num1) {
this.num1 = num1;
}
public X getNum2() {
return num2;
}
public void setNum2(X num2) {
this.num2 = num2;
}
// 测试
public static void main(String[] args) {
TwoNumGeneric<Integer, Float> twoNumGeneric = new TwoNumGeneric<>();
twoNumGeneric.genericNum(10, 5.0f);
System.out.println("num1=" + twoNumGeneric.getNum1() + ",num2=" + twoNumGeneric.getNum2());
}
}
- 4.运行代码,结果如下。
4、自定义泛型方法
- 泛型方法不一定非得写在泛型类当中。
- 新建一个类GenericMethod,代码如下,结果图略。
public class GenericMethod {
// <T>必须位于访问修饰符和返回值之间,代表为泛型方法
public <T> void printValue(T t) {
System.out.println(t);// 这里仅作演示,代码比较简单
}
// 测试
public static void main(String[] args) {
GenericMethod gm = new GenericMethod();
gm.printValue("chaixingsi");
gm.printValue(123);
gm.printValue(7.89);
}
}
- 2.也可以将泛型方法定义为如下形式,将其参数限制为Number及其子类类型。
public <T extends Number> void printValue(T t) {
System.out.println(t);// 这里仅作演示,代码比较简单
}