自定义泛型
大约 3 分钟
自定义泛型
自定义泛型类
基本语法
class 类名 <T, R...> { // ... 表示可以有多个泛型
成员
}
注意细节
- 普通成员可以使用泛型(属性、方法)
- 使用泛型的数组,不能初始化
- 静态方法中不能使用类的泛型
- 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
- 如果在创建对象时,没有指定类型,默认为 Object
示例
/**
* 1. Tiger 后面泛型,所以我们把 Tiger 就称为自定义泛型类
* 2. T,R,M 泛型的标识符,一般是单个大写字母
* 3. 泛型标识符可以有多个
* 4. 普通成员可以使用泛型(属性、方法)
* 5. 使用泛型的数组,不能初始化
* 6. 静态方法和静态属性(static)中不能使用类的泛型,所以会报错
*/
class Tiger<T, R, M>{
String name;
R r;
M m;
T t;
T[] ts;
/**
* 因为静态是和类相关的,在类加载时,对象还没有创建所以,
* 所以,如果静态方法和静态属性使用了泛型,JVM就无法完成初始化
*/
static R r2; // 报错
public static void m1(M m) {} // 报错
}
泛型接口
基本语法
interface 接囗名<T, R...>{
}
注意细节
- 接口中,静态成员也不能使用泛型(这个和泛型类规定一样)
- 泛型接口的类型,在 继承接口 或者 实现接口 时确定
- 没有指定类型,默认为 Object
示例
interface IUsb<U, R> {
int n = 10;
U name; // 不能这样使用,因为在接口中都是静态属性
R get(U u); // 普通方法中,可以使用接口泛型
void hi(R r); // 普通方法中,可以使用接口泛型
}
/**
* 泛型接口的类型,在 继承接口 或者 实现接口 时确定
* IA 继承了 IUsb 并且规定 U 的类型为 String R 的类型为 Double
*/
interface IA extends IUsb<String, Double> {}
/**
* 当我们去实现 IA 接口时,因为 IA 在继承 IUsU 接口时,指定了 U 为 String R 为 Double
* 因此,在实现 IUsu 接口的方法时,使用 String 替换 U,Double 替换 R
*/
class AA implements IA{
@Override
public Double get(String s) {
return null;
}
@Override
public void hi(Double aDouble) {
}
}
/**
* 实现接口时,直接指定泛型接口的类型
* 给 U 指定 Integer 给 R 指定了 Float
* 所以,当我们实现 IUsb 方法时,会使用 Integer 替换 U,使用 Float 替换 R
*/
class BB implements IUsb<Integer, Float> {
@Override
public Float get(Integer integer) {
return null;
}
@Override
public void hi(Float aFloat) {
}
}
泛型方法
基本语法
修饰符 <T, R..>返回类型 方法名(参数列表){
}
注意细节
- 泛型方法,可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时,类型会确定
public void eat(E e){}
,修饰符后没有<T,R..> eat
方法不是泛型方法,而是使用了泛型
示例
package commonGenericity;
import java.util.ArrayList;
import java.util.function.IntToDoubleFunction;
public class customGenerics {
public static void main(String[] args) {
Car car = new Car();
car.fly("宝马", 1000);
System.out.println("==============================");
car.fly(2000, 300);
/**
* 测试
* T ---> String, R ---> ArrayList
*/
Fish<String, ArrayList> stringIntegerFish = new Fish<>();
stringIntegerFish.hello(new ArrayList(), 11.3f);
}
}
class Car { // 普通类
public void run() {}; // 普通方法
/**
* 说明
* 1. <T, R> 就是泛型
* 2. 是提供给 fly 使用的
*/
public <T, R> void fly(T t, R r) { // 泛型方法
System.out.println(t.getClass()); // String
System.out.println(r.getClass()); // Integer
}
}
class Fish<T, R> { // 泛型类
public void run() {} // 普通方法
public<U, M> void eat(U u, M m) {} // 泛型方法
/**
* 说明
* 1. 下面 hi 方法不是泛型方法
* 2. 是 hi 方法使用了类声明的 泛型
*/
public void hi(T t) {}
/**
* 泛型方法,可以使用类声明的泛型,也可以使用自己声明泛型
*/
public<K> void hello(R r, K k){
System.out.println(r.getClass());
System.out.println(k.getClass());
}
}