🍋1. 泛型的定义
class 类名称<泛型标识, 泛型标识, ....>{
private 泛型标识 变量名称;
.......
}
常用的泛型标识字符 :T, E, K, V
- E - Element (在集合中使用,由于集合中存放的是元素),E是对各方法中的泛型类型进行限制,以保证同一个对象调用不一样的方法时,操做的类型一定是相同的。E能够用其它任意字母代替
- T - Type(Java 类),T表明在调用时的指定类型。会进行类型推断
- K - Key(键)
- V - Value(值)
- N - Number(数值类型)
我们以下面代码为例定义一个泛型类
public class Test<T> {
private T key;
public Test(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 +
'}';
}
}
创建一个泛型类对象, 并指定为String类型
public static void main(String[] args) {
//这里我们指定的String类型
Generic<String> str = new Generic<>("aaa");
//返回的类型也是String
String key = str.getKey();
//这里我们指定的Integer类型
Generic<Integer> integer = new Generic<>(1);
//返回的类型也是Integer
Integer key1 = integer.getKey();
}
🍓2. 泛型的两种继承
方式1 : 泛型派生子类, 子类也是泛型, 那么子类的泛型标识要个父类的保持一致
public class Child<T> extends Parent<T> {
}
方式2 : 泛型派生子类, 如果子类不是泛型类, 那么父类要明确数据类型
public class ChildTow extends Parent<Integer> {
}
🍔3. 泛型接口
/**
* 泛型接口
* @param <T>
*/
public interface Generator<T> {
T getKey();
}
方式1 : 实现泛型接口的类不是泛型, 需要明确实现泛型接口的数据类型
public class Apple implements Generator<String>{
@Override
public String getKey() {
return "hello";
}
}
方式2 : 泛型接口的实现类, 是一个泛型类, 那么要保证实现接口的泛型类标识 和泛型接口的一致
public class Pair<T, E> implements Generator<T> {
@Override
public T getKey() {
return null;
}
}
🍭4. 泛型方法
泛型方法的定义
/**
* 测试自定义泛型方法
* @param list 参数
* @param <E> 泛型标识, 具体类型, 由调用方法的时候来指定
* @return
*/
public <E> E getOne(ArrayList<E> list){
//返回第一个元素
return list.get(0);
}
泛型方法的调用 : 泛型方法的调用, 类型是通过调用方法的时候来指定的
public static void main(String[] args) {
Test test = new Test();
ArrayList<String> str = new ArrayList<>();
str.add("测试001");
String one = test.getOne(str);
System.out.println("one = " + one);
ArrayList<Integer> num = new ArrayList<>();
num.add(996);
System.out.println("num = " + num);
}
静态泛型方法的定义(多个参数) 泛型可变参数的定义
/**
* 泛型可变参数的定义
* @param e
* @param <E>
*/
public static <E> void print(E... e){
for (E value : e) {
System.out.println("参数 : " + value);
}
}
//调用
Test.print("测试", 111, 2.2, new ArrayList<>());
🥭5. 泛型类型通配符
1. 类型通配符上线 :
要求该泛型的类型, 只能是实参类型, 或者实参类型子类的类型
下面以Integer为例, 它的父类就是Number类型, 这一点我们从源码中就能得知
实现代码如下,
public static void showBox(Box<? extends Number> box){
Number first = box.getFirst();
System.out.println("first = " + first);
}
我们最后传入的参数只能是Number以及他的子类Integer类型
public static void main(String[] args) {
Box<Integer> objectBox = new Box<>();
objectBox.setFirst(11111);
showBox(objectBox);
}
2.类型通配符下线 :
要求该泛型的类型, 只能是实参类型, 或者实参类型父类的类型
这里为了便于讲解实现了三个类
/**
* 爷爷类
*/
public class Grandfather {
}
/**
* 父亲类
*/
public class Father extends Grandfather{
}
/**
* 儿子类
*/
public class Son extends Father {
}
下线通配符代码实现如下
public static void family(List<? super Father> item){
for (Object o : item) {
System.out.println(o);
}
}
//调用
family(new ArrayList<Son>());
family(new ArrayList<Grandfather>());
可以看出当下线设置为<? super Father> 的时候传入的参数只能是爸爸的上级也就是爷爷类(Grandfather), 传入儿子类(Son)就会产生报错
🍖6. 泛型代码
扫描下方公众号二维码 回复: 泛型 即可领取项目源码 👇👇👇