1.定义
定义:泛型(Generics)是参数化类型的应用,即把类型(如类、接口、方法等)参数化,使之能够接受不同类型的参数。这种参数类型在编译时会被检查,从而确保类型安全,并避免了在运行时出现类型转换错误。
2.特点
- 类型安全:泛型通过编译时的类型检查,避免了在运行时出现类型转换错误,提高了程序的稳定性和安全性。
- 代码重用:使用泛型可以编写更加通用、可重用的代码。例如,可以编写一个泛型集合类,用于存储任意类型的数据。
- 清晰的代码:泛型的使用使得代码更加清晰、易于理解和维护。类型参数清晰地指示了代码的目的和使用方法。
3.应用场景
- 泛型类:在定义类时使用泛型参数,使得类在实例化时可以接受不同类型的数据。例如,ArrayList就是一个泛型类,其中的E是一个类型参数,表示ArrayList可以存储的元素类型。
- 泛型接口:在定义接口时使用泛型参数,使得接口具有更大的灵活性和复用性。实现泛型接口的类需要指定具体的类型参数。
3.泛型方法:在定义方法时使用泛型参数,使得方法可以在不同的数据类型上进行操作。泛型方法可以在普通类中定义,也可以在泛型类中定义。
4.示例
package com.imooc.generics;
public class Box<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
public static void main(String[] args) {
Box<Integer> integerBox = new Box<>();
integerBox.set(123);
System.out.println(integerBox.get()); // 输出 123
Box<String> stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get()); // 输出 Hello
}
}
在这个示例中,Box是一个泛型类,它有一个类型参数T。在实例化Box时,可以指定T的具体类型,如Integer或String。这样,Box就可以存储任意类型的数据,并在编译时进行类型检查。
5.总结
Java泛型是一种强大的特性,它提高了代码的重用性、可读性和类型安全性。通过使用泛型,程序员可以编写更加灵活、通用的代码,同时避免了在运行时出现类型转换错误。泛型是Java编程中不可或缺的一部分,掌握它对于编写高质量的Java程序至关重要。
6.泛型作为方法参数
案例需求:
- 定义一个抽象类Goods。包含抽象方法sell()
- 分别定义类Book、Clothes、Shoes继承Goods,并实现sell()方法,输出一句话,如sell books
- 定义一个商品销售类GoodsSeller,模拟销售,包含方法public void sellGoods(List goods),循环调用List对象的sell()方法
Goods类
package com.imooc.generics;
abstract class Goods {
// 抽象方法,没有方法体
abstract void sell();
// 抽象类也可以包含具体的方法
void show() {
System.out.println("表演");
}
}
Book类
package com.imooc.generics;
public class Books extends Goods{
@Override
void sell() {
System.out.println("卖书");
}
}
Clothes类
package com.imooc.generics;
public class Clothes extends Goods{
@Override
void sell() {
System.out.println("卖衣服");
}
}
Shoes类
package com.imooc.generics;
public class Shoes extends Goods{
@Override
void sell() {
System.out.println("卖鞋");
}
}
GoodsSeller
package com.imooc.generics;
import java.util.List;
public class GoodsSeller {
public void sellGoods(List<? extends Goods> goods) {
//增强for循环 调用传入对象的方法
for (Goods good : goods) {
good.sell();
}
}
}
测试类
package com.imooc.generics;
import java.util.ArrayList;
import java.util.List;
public class GoodsTest {
public static void main(String[] args) {
//定义存放book对象的数组
List<Books> books = new ArrayList<>();
//往数组里添加book对象
books.add(new Books());
books.add(new Books());
List<Clothes> clothes = new ArrayList<>();
List<Shoes> shoes = new ArrayList<>();
GoodsSeller goodsSeller = new GoodsSeller();
goodsSeller.sellGoods(books);
}
}
List<? extends Goods> goods: 只要是添加进来的泛型是Goods类或者它的子类都是可以的。
6.自定义泛型类
单个类型:
package com.imooc.generics;
public class Number<T> {
private T num;
public void setNumber(T num) {
this.num = num;
}
public T getNum(){
return num;
}
public static void main(String[] args) {
Number<String> number = new Number<>();
number.setNumber("张三");
System.out.println(number.getNum());
Number<Double> number2 = new Number<>();
number2.setNumber(3.14);
System.out.println(number2.getNum());
}
}
多个类型
package com.imooc.generics;
public class NumberTwo <T,X>{
private T num1;
private X num2;
public void genNum(T num1, X num2){
this.num1 = num1;
this.num2 = num2;
}
public X getNum2() {
return num2;
}
public void setNum2(X num2) {
this.num2 = num2;
}
public T getNum1() {
return num1;
}
public void setNum1(T num1) {
this.num1 = num1;
}
public static void main(String[] args) {
NumberTwo<String,Integer> numberTwo = new NumberTwo<String,Integer>();
numberTwo.genNum("年龄",18);
System.out.println(numberTwo.getNum1());
System.out.println(numberTwo.getNum2());
}
}
7.自定义泛型方法
package com.imooc.generics;
public class Method {
//泛型方法不一定写在泛型类中
public <T> void printValue(T t){
System.out.println(t);
}
//规定泛型方法传入的类型为String
public <T extends String> void printValue2(T t){
System.out.println(t);
}
public static void main(String[] args) {
Method m = new Method();
//传入各种类型的数据
m.printValue(1);
m.printValue("张三");
System.out.println("----------------------");
Method m2 = new Method();
//m2.printValue2(1); 方法printValue2规定传入的类型为String,则不允许其他类型的数据
m2.printValue2("李四");
}
}