文章目录
前言
本篇文章主要讲解泛型最基本的定义与用法,为后续Java的学习打牢基础
一、泛型类的定义
-
1.1 泛型类的定义语法
class 类名称 <泛型标识、泛型标识、...> {
private 泛型标识 变量名;
......
}
常用的泛型标识 T、E、K、V
-
1.2 代码使用示例
/**
* 泛型类的定义
*/
public class Generic<T> {
// T 是由外部使用类的时候来指定的。
private T key;
public Generic(T key) {
this.key = key;
}
public T getKey() {
return key;
}
public void setKey(T key) {
this.key = key;
}
@Override
public String toString() {
return "Generic{" +
"key=" + key +
'}';
}
}
二、泛型类的使用语法
-
2.1 使用语法
//使用语法
类名<具体的数据类型> 对象名 = new 类名<具体的数据类型>();
//java 1.7以后,后边的<>中具体的数据类型可以省略不写
类名<具体的数据类型> 对象名 = new 类名<>();
-
2.2 泛型类注意事项
- 泛型类如果没有指定具体的数据类型,此时,操作类型是Object
- 泛型的类型参数只能是类类型,不能是基本数据类型
- 泛型类型在逻辑上可以看成是多个不同的类型,但实际上是相同类型
-
2.3 泛型类的使用小案例
年终抽奖器案例:
/**
* 抽奖器
*/
public class ProductGetter<T> {
//奖金或者奖品
private T product;
//定义奖品、奖金池
ArrayList<T> arrayList = new ArrayList<>();
//添加奖品到奖品池
public void addProduct(T t) {
arrayList.add(t);
}
//定义一个随机数、用来抽选奖品
Random random = new Random();
//抽奖
public T getProduct() {
product = arrayList.get(random.nextInt(arrayList.size()));
return product;
}
}
public class Test {
public static void main(String[] args) {
ProductGetter<String> stringProductGetter = new ProductGetter<>();
String[] strPro = {"华为手机", "苹果手机", "扫地机器人", "咖啡机"};
//将奖品放入奖金池
for(int i = 0;i < strPro.length;i++){
stringProductGetter.addProduct(strPro[i]);
}
String product = stringProductGetter.getProduct();
System.out.println("恭喜您抽中了,"+product);
System.out.println("************************************");
ProductGetter<Integer> IntegerProductGetter = new ProductGetter<>();
Integer[] intPro = {100,1000,10000,20000};
//将奖品放入奖金池
for(int i = 0;i < intPro.length;i++){
IntegerProductGetter.addProduct(intPro[i]);
}
Integer product1 = IntegerProductGetter.getProduct();
System.out.println("恭喜您,获得了:"+product1+"元");
}
}
可以将上述案例自己敲一遍进行理解,若能全部理解则说明已经入门
三、从泛型类派生子类(2种情况)
1、子类也是泛型类,子类和父类的泛型类型要保持一致
class ChildGeneric<T> extends Generic<T>
2、子类不是泛型类,父类要明确泛型类的数据类型
class ChildGeneric extends Generic<String>
-
3.1 子类和父类的泛型类型要保持一致
定义父类如下:
public class Parent<E> {
private E value;
public E getValue() {
return value;
}
public void setValue(E value) {
this.value = value;
}
}
定义子类如下:
/**
* 泛型类派生子类,如果子类也是泛型类,子类的泛型标识要和父类一致。
* @param <T>
*/
public class ChildFirst<T> extends Parent<T> {
@Override
public T getValue() {
return super.getValue();
}
}
定义测试类如下:
public class Test {
public static void main(String[] args) {
ChildFirst<String> childFirst = new ChildFirst<>();
childFirst.setValue("123");
String value = childFirst.getValue();
System.out.println(value);
}
}
子类和父类的泛型类型要保持一致,而在创建子类的过程中,我们可以发现如下问题:
可以看到,如果不对父类指定数据类型,则会默认为Object,虽然可以成功创建子类,但是可能会导致后续内容的报错
而如果父类指定了数据类型,但是和子类指定的数据类型不同,则会在创建子类时就进行报错
-
3.2 子类没有使用泛型
当子类没有使用泛型时,父类的泛型类操作的就是一个Object,可以从重写的getValue()方法的返回值看出来,父类提供的类型是Object
当子类没有使用泛型时,父类也无法指定泛型,因为在创建子类对象时,我们无法确定父类的泛型所使用的数据类型
也因此,我们需要明确父类的数据类型,以此避免后续因使用Object类型而可能出现的问题
四、泛型接口
-
4.1 泛型接口的语法定义
interface 接口名称 <泛型标识,泛型标识,...>{
泛型标识 方法名();
......
}
代码使用示例:
/**
* 泛型接口
*/
public interface Igeneric<T> {
abstract T getName(T name);
}
-
4.2 泛型接口的使用(2种情况)
- 实现类不是泛型类,接口要明确数据类型
- 实现类也是泛型类,实现类和接口的泛型类型要一致
(大致用法与泛型类相同,注意接口与类的区别即可)