23.泛型让类型更加规范性

为什么使用泛型

在Java增加泛型之前,泛型程序设计使用继承来实现的,可其中也有不便,需要强制类型转换以及可向集合中添加任意类型的对象,存在一定的风险
因此使用泛型就是为了避免需要强制类型转换以及运行时异常的安全隐患,可以控制问题在编译时报错。

使用泛型

List<String> list = new ArrayList<String>();

在Java SE7以后的版本中,构造方法中可以省略泛型类型

List<String> list = new ArrayList<>();

多态与泛型

变量声明的类型必须匹配传递给实际对象的类型
错误示例:

List<Object> list = new ArrayList<String>();
List<Number> list = new ArrayList<Ingeger>();

泛型作为方法参数

案例:

  • 定义一个抽象类Goods ,包含抽象方法sell()分别定义类Book、Clothes和Shoes继承Goods ,并实现sell()方法,输出一-句话,如:sell books
  • 定义一个商品销售类GoodsSeller ,模拟销售,包括方法:
    public void sellGoods(List <Goods> goods),循环调用List对象的sell()方法。
// 抽象类Goods 
public abstract class Goods {
	public abstract void sell();
}
// 实现类Book
public class Book extends Goods {
	@Override
	public void sell() {
		System.out.println("sell books");
	}
}
// 实现类Clothes 
public class Clothes extends Goods {
	@Override
	public void sell() {
		System.out.println("sell clothes");
	}
}
// 实现类Shoes 
public class Shoes extends Goods {
	@Override
	public void sell() {
		System.out.println("sell shoes");
	}
}

商品销售类GoodsSeller:

public class GoodsSeller {
	// 此处通过 List<? extends Goods> goods 的方式,规Goods和Goods的子类都可以添加,且限制类型的单一
	public void sellGoods(List<? extends Goods> goods) {
		// 遍历goods
		for(Goods g : goods) {
			g.sell();	// 调用sell方法
		}
	}
}

定义方法参照ArrayList构造方法:

规定E类与E的子类都可以传入,不仅可以extends类,也可以extends接口
23.泛型让类型更加规范性

同时还可以进行通过实现超类的声明:

// // 此处通过 List<? super Goods> goods 的方式,规定Goods和Goods的超类都可以添加,且限制类型的单一
public void sellGoods(List<? super Goods> goods){

}

测试类:

		List<Book> books = new ArrayList<>();
		books.add(new Book());
		books.add(new Book());
		books.add(new Book());
				
		GoodsSeller goodsSeller = new GoodsSeller();
		goodsSeller.sellGoods(books);

自定义泛型

定义泛型类1:(一种类型)

// T表示不确定什么类型
public class NumGeneric<T> {
	// 同样适用T代替
	private T num;
	public T getNum() {
		return num;
	}
	public void setNum(T num) {
		this.num = num;
	}
}

测试类:

		NumGeneric<Integer> intNum = new NumGeneric<>();
		intNum.setNum(10);
		System.out.println("Integer数为:" + intNum.getNum());
		
		NumGeneric<Float> intFloat = new NumGeneric<>();
		intFloat.setNum(3.1f);
		System.out.println("Float数为:" + intFloat.getNum());

通过自定义泛型,把数据类型参数化

定义泛型类2:(两种类型)

public class TowNumGeneric<T, X> {

	private T num1;
	private X num2;
	public void Num(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;
	}
	
}

测试类:

		TowNumGeneric<Integer, Double> num = new TowNumGeneric<>();
		num.Num(20, 3.99);
		System.out.println("num1数为:" + num.getNum1());
		System.out.println("num2数为:" + num.getNum2());

自定义泛型方法

public class GenericMethond {
	// 不确定数据类型
	public <T> void printValue(T t) {
		System.out.println(t);
	}
	// 不确定数据类型,但必须是Number的子类
	public <T extends Number> void printNum(T t) {
		System.out.println(t);
	}
}

测试类:

		GenericMethond gm = new GenericMethond();
		gm.printValue("hello");
		gm.printValue(3.9f);
		gm.printValue(3);
		
		// printNum()里不可传字符串,必须是数值型
		gm.printNum(20);
上一篇:Mysql操作记录


下一篇:flask中的关联关系:一对多