泛型类型变量的限定
泛型的基础知识可以参考其他教程。
如果在方法前指定了<T>,那么就是说,方法的这个泛型类型和类定义时的泛型类型无关,这个特性让泛型方法可以定义在普通类中而不是泛型类中。
我们都知道,泛型中可以限定类型变量必须实现某几个接口或者继承某个类,多个限定类型用&分隔,类必须放在限定列表中所有接口的前面。例如:
[java] view plain copy
- import java.io.Serializable;
- /**
- * ICE
- * 2016/10/17 0017 14:12
- */
- public class Demo {
- public static void main(String[] args) {
- D<A> d = new D<>();
- A a = new A();
- d.test1(a);
- B b = new B();
- d.test1(b);
- C c = new C();
- d.test1(c);
- d.test2("test");
- }
- }
- class A implements Serializable, Cloneable {
- @Override
- public String toString() {
- return "A{}";
- }
- }
- class B extends A {
- @Override
- public String toString() {
- return "B{}";
- }
- }
- class C extends A {
- @Override
- public String toString() {
- return "C{}";
- }
- }
- class D<T extends A & Serializable & Cloneable> {
- public void test1(T t) {
- System.out.println(t);
- }
- public <T> void test2(T t) {
- System.out.println(t);
- }
- }
输出:
[plain] view plain copy
- A{}
- B{}
- C{}
- test
通配符类型
通配符“?”同样可以对类型进行限定。可以分为子类型限定、超类型限定和无限定。通配符不是类型变量,因此不能在代码中使用"?"作为一种类型。
子类型限定
表示类型的上界,类似泛型的类型变量限定,格式是:? extends X。
特点:
1、限定为X和X的子类型,但不知道具体是哪个子类型,可能是怕导致类型转换错误(比如向下转型时编译不会报错,但是如果超类引用不是指向子类对象,那么运行时会报错),所以作为方法的参数时,这里禁止传递特定的类型。
2、作为方法的参数时,可以传递null。
作用:主要用来安全地访问数据,可以访问X及其子类型。
[java] view plain copy
- import java.util.ArrayList;
- import java.util.List;
- /**
- * ICE
- * 2016/10/17 0017 14:12
- */
- public class Demo {
- public static void main(String[] args) {
- A a = new A();
- B b = new B();
- C c = new C();
- List<A> list = new ArrayList<>();
- list.add(a);
- list.add(b);
- list.add(c);
- //根据list的值,我们可以给列表中的对象做<? extends A>限定,因为都是A和A的子类,get返回值赋给A是完全合法的
- List<? extends A> list1 = list;
- list.add(null);
- for (int i = 0; i < list1.size(); i++) {
- A a1 = list1.get(i);
- System.out.println(a1);
- }
- //这里如果set任何非null的值,编译器都会报错
- D<? extends A> d = new D<>();
- d.set(null);
- }
- }
- class A {
- @Override
- public String toString() {
- return "A{}";
- }
- }
- class B extends A {
- @Override
- public String toString() {
- return "B{}";
- }
- }
- class C extends A {
- @Override
- public String toString() {
- return "C{}";
- }
- }
- class D<T> {
- public void test1(T t) {
- System.out.println(t);
- }
- public void set(T t) {
- }
- }
输出:
[plain] view plain copy
- A{}
- B{}
- C{}
- null
超类型限定
表示类型的下界,格式是:? super X。
特点:
1、限定为X和X的超类型,直至Object类,因为不知道具体是哪个超类型,因此方法返回的类型只能赋给Object。
2、因为可以向上转型,所以作为方法的参数时,可以传递X以及X的子类型。
3、作为方法的参数时,可以传递null。
作用:主要用来安全地写入数据,可以写入X及其子类型。
[java] view plain copy
- /**
- * ICE
- * 2016/10/17 0017 14:12
- */
- public class Demo {
- public static void main(String[] args) {
- A a = new A();
- B b = new B();
- C c = new C();
- D<? super A> d = new D<>();
- Object o = d.get();
- d.set(a);
- d.set(b);
- d.set(c);
- d.set(null);
- }
- }
- class A {
- @Override
- public String toString() {
- return "A{}";
- }
- }
- class B extends A {
- @Override
- public String toString() {
- return "B{}";
- }
- }
- class C extends A {
- @Override
- public String toString() {
- return "C{}";
- }
- }
- class D<T> {
- public void set(T t) {
- }
- public T get() {
- return null;
- }
- }
无限定
无限定不等于可以传任何值,相反,作为方法的参数时,只能传递null,作为方法的返回时,只能赋给Object。
[java] view plain copy
- /**
- * ICE
- * 2016/10/17 0017 14:12
- */
- public class Demo {
- public static void main(String[] args) {
- D<?> d = new D<>();
- Object o = d.get();
- d.set(null);
- }
- }
- class A {
- @Override
- public String toString() {
- return "A{}";
- }
- }
- class B extends A {
- @Override
- public String toString() {
- return "B{}";
- }
- }
- class C extends A {
- @Override
- public String toString() {
- return "C{}";
- }
- }
- class D<T> {
- public void set(T t) {
- }
- public T get() {
- return null;
- }
- }
有什么作用呢?对于一些简单的操作比如不需要实际类型的方法,就显得比泛型方法简洁。
[java] view plain copy
- /**
- * ICE
- * 2016/10/17 0017 14:12
- */
- public class Demo {
- public static void test(D<?> d) {
- System.out.println(d == null);
- }
- public static <T> void test1(D<T> d) {
- System.out.println(d == null);
- }
- public static void main(String[] args) {
- D d = new D();
- Demo.test(d);
- Demo.test1(d);
- }
- }
- class D<T> {
- }