Java泛型

Java泛型是从JDK5中新加入的一个新特性。泛型提供了编译时类型安全检测机制,该机制可以在编译时检测到非法的类型。

泛型类

定义泛型类:

public class GenericClass<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}

测试:

public class DemoGenericClassTest {
    public static void main(String[] args) {
        GenericClass<Integer> gc = new GenericClass<>();
        gc.setName(1);
        Integer name = gc.getName();
        System.out.println(name);
    }
}

注:

  • 泛型类可能有多个参数,此时应该将多个参数一起放在尖括号内,比如<E1,E2,E3>
  • 泛型类的构造器是:public GenericClass(){},而不是public GenericClass<E>{}

泛型接口

语法:

修饰符 interface 接口名<代表泛型的变量>{}

定义含有泛型的接口:

/**
 * 定义含有泛型的接口
 */
public interface GenericInterface<I> {
    public abstract void method(I i);

}

使用含有泛型接口的第一种方式

创建类实现含有泛型的接口:

/**
  含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型
*/
public class GenericInterfaceImpl1 implements GenericInterface<String> {
    @Override
    public void method(String s) {
        System.out.println(s);
    }
}

测试含有泛型的接口:

public class DemoGenericInterfaceTest {
    public static void main(String[] args) {
        GenericInterfaceImpl1 gi1 = new GenericInterfaceImpl1();
        gi1.method("你好");
    }
}

使用含有泛型接口的第二种方式

创建类实现接口:

/**
 * 含有泛型的接口第二种使用方式:接口使用什么类型,实现类就使用什么泛型,类跟着接口走
 * 就相当于定义一个含有泛型的类,创建对象的时候确定泛型的类型
 */
public class GenericInterfaceImpl2<I> implements GenericInterface<I> {
    @Override
    public void method(I i) {
        System.out.println(i);
    }
}

测试:

public class DemoGenericInterfaceTest {
    public static void main(String[] args) {
        GenericInterfaceImpl2<Integer> gi2 = new GenericInterfaceImpl2<>();
        gi2.method(10);
    }
}

泛型方法

语法:

修饰符 <代表泛型的变量> 返回值类型 方法名(参数){}

定义泛型方法:

public class GenericMethod {
    public <M> void method1(M m) {
        System.out.println(m);
    }

    public static <S> void method2(S s) {
        System.out.println(s);
    }
}

测试如下:

public class DemoGenericMethodTest {
    public static void main(String[] args) {
        //创建GenericMethod对象
        GenericMethod gm = new GenericMethod();
        gm.method1(10);
        gm.method1("abc");
        gm.method1(1.34);

        //使用类名直接调用静态方法
        GenericMethod.method2("def");
        GenericMethod.method2(123);
    }
}

泛型通配符

当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示,一旦使用泛型的通配符,只能使用Object类中的共性方法,集合元素自身方法无法使用。

当不知道使用什么类型来接收的时候,此时可以使用??表示未知通配符。

/**
 * 泛型的通配符
 * ?: 代表任意的数据类型
 * 使用方式:
 * 不能创建对象使用
 * 只能作为方法的参数使用
 */
public class DemoGeneric {
    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");

        printArray(list01);
        printArray(list02);
    }

    public static void printArray(ArrayList<?> list) {
        Iterator<?> it = list.iterator();
        while (it.hasNext()) {
            Object o = it.next();
            System.out.println(o);
        }
    }
}

泛型的上下限

泛型的上限:

  • 类型名称<? extends 类> 对象名称:只能接收该类型及其子类

泛型的下限:

  • 类型名称<? super 类> 对象名称:只能接收该类型及其父类型
import java.util.ArrayList;
import java.util.Collection;

/**
 * 泛型的上限限定: ? extends E 使用的泛型只能是E类型的子类/本身
 * 泛型的下限限定: ? super E 使用的泛型只能是E类型的父类/本身
 */
public class TestGeneric {
    public static void main(String[] args) {
        Collection<Integer> list1 = new ArrayList<>();
        Collection<String> list2 = new ArrayList<>();
        Collection<Number> list3 = new ArrayList<>();
        Collection<Object> list4 = new ArrayList<>();
        getElement1(list1);
//        getElement1(list2); //报错
        getElement1(list3);
//        getElement1(list4); //报错

//        getElement2(list1); //报错
//        getElement2(list2); //报错
        getElement2(list3);
        getElement2(list4);

    }

    //泛型的上限
    public static void getElement1(Collection<? extends Number> coll) {

    }

    //泛型的下限
    public static void getElement2(Collection<? super Number> coll) {

    }
}
上一篇:Java学习之Java面试题


下一篇:学习Java集合框架,看这一篇就够了