泛型概念
是一种未知的数据类型,当不知道用什么数据类型的时候,就可以使用泛型。
泛型也可以看作是一个变量,用来接收数据类型:
E e: Element 元素
T t : Type 类型
如ArrayList<E>源码中也是使用的泛型。
创建对象的时候,会确定泛型的数据类型
ArrayList<String> list = new ArrayList<String>();,
会把握String赋值 给泛型E。
泛型类
package com.fx;
/**
* T: 参数化类型,只有在使用时要指定具体的类型
* @param <T>
*/
public class Node<T> {
private T data;
public Node(){}
public Node(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
package com.fx;
import org.junit.jupiter.api.Test;
public class FxTest {
@Test
public void testNOde(){
Node<String> n = new Node<>("111");
System.out.println(n.getData());
}
}
泛型普通方法和静态方法
package com.generic;
/**
* 定义含有型的方法 :泛型定义在方法的修饰符和返回值类型之间
*/
public class GenericMethod {
//定义一个含有泛型的方法
//下面这个K也可以是任一其他字母
public <K> void method01(K k){
System.out.println(k);
}
定义一个含有泛型的静态方法
public static<K> void method02(K k){
System.out.println(k);
}
}
package com.generic;
import org.junit.jupiter.api.Test;
public class GenercMethodTest {
@Test
public void test01(){
//调用含有泛型的方法method01
//传递什么类型,泛型就是什么类型
GenericMethod gm = new GenericMethod();
gm.method01("这是一个字符串");
gm.method01(11.22);
}
@Test
public void test02(){
//调用含有泛型的静态方法method01
//传递什么类型,泛型就是什么类型
GenericMethod.method02("这是一个字符串");
GenericMethod.method02(11.22);
}
}
接口中使用泛型
package com.itf;
/**
* 定义含有泛型的接口
* @param <I>
*/
public interface GenericInterface<I> {
public abstract void method(I i);
}
第一种使用方式 : 实现类中指定接口的泛型
package com.itf;
/*
定义接口的实现类,实现接口,指定接口的泛型
*/
public class GenericInterfaceImpl1 implements GenericInterface<String> {
@Override
public void method(String s) {
System.out.println(s);
}
}
package com.itf;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* 测试含有泛型的接口
*/
class GenericInterfaceImpl1Test {
@Test
void method() {
GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
gi1.method("这是字符串");
}
}
第二种方式:创建对象时指定泛型
package com.itf;
/**
* 接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
* 也就是说定义了一个含有泛型的类,创建对象的时候确定泛型
*/
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
@Override
public void method(I i) {
System.out.println(i);
}
}
package com.itf;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
//测试含有泛型的接口,第二种方式
class GenericInterfaceImpl2Test {
@Test
void method() {
//创建GenericInterfaceImpl2对象
GenericInterface<Integer> gi2 = new GenericInterfaceImpl2();
gi2.method(100);
GenericInterface<String> gi3= new GenericInterfaceImpl2();
gi3.method("100");
}
}
泛型通配符?
当使用泛型或接口时,传递的数据中,泛型不确定,可以通过通配符<?>表示,但只要使用通配符后,只能使用Object类中的共性方法了,集合中元素自身方法无法使用。
通配符基本使用
不知道使用什么类型来接收的时候,可以使用泛型?,?表示未知道通配符,
此时只能接受数据,不能往集合中存储数据
package com.itf;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 泛型的通配符:
* ?: 代表任意的数据类型
* 使用方式:
* 不能创建对象时使用
* 只能作为方式的参数使用
*/
public class GenericDemo {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
listArray(list01);
listArray(list02);
}
/**
* 这时候我们不知道要接收的ArrayList集合使用什么数据类型,
* 可以使用泛型的通配符?来接收数据类型
* 注意:
* 泛型没有继承的概念
*/
public static void listArray(ArrayList<?> list){
//使用迭代器遍历集合
Iterator<?> it = list.iterator();
while (it.hasNext()){
//it.next()方法,取出来的元素是Object,可以接收任意数据类型
Object o = it.next();
System.out.println(o);
}
}
}
通配符高级使用 ---受限泛型
上面设置泛型的泛型,实际上是可以任意设置的,只要是类就可以设置,但是在java的泛型中可以指定一个泛型的上限和下限。
泛型的上限:
格式:类型名称<? extends 类> 对象名称
意义:只能接收该及其子类
泛型的下限:
格式:类型名称<? super类> 对象名称
意义:只能接收该及其父类
package com.itf;
import java.util.ArrayList;
import java.util.Collection;
/**
* 泛型的上限限定: ? extends E 代表使用的泛型只能是E类型的子类/本身
* 泛型的下限限定: ? super E 代表使用的泛型只能是E类型的父类/本身
*/
public class GenercDemo02 {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement1(list1);
getElement1(list2); //报错
getElement1(list3);
getElement1(list4);//报错
getElement2(list1);//报错
getElement2(list2);//报错
getElement2(list3);
getElement2(list4);
}
//泛型的上限: 此时的泛型?,必须是Number类型或Number类型的子类
public static void getElement1(Collection<? extends Number> coll){};
//泛型的下限: 此时的泛型?,必须是Number类型或Number类型的父类
public static void getElement2(Collection<? super Number> coll){};
}