Java泛型中的类型变量限定和通配符类型限定

类型变量限定
如果在方法前指定了<T>,那么这个方法的泛型类型和类定义的泛型类型无关,这个特性让泛型方法可以定义在普通类中而不是泛型类中。
泛型可以限定类型变量必须实现某几个接口或者继承某个类,多个限定类型用&分隔,类必须放在限定列表中所有接口的前面。
例如:
import java.io.Serializable;
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);
//test2泛型方法传入的类型是String,不是 D<A> d = new D<>();定义的A类型
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);
}
}
 
输出:
A{}
B{}
C{}
test
 
通配符类型限定
通配符“?”同样可以对类型进行限定。可以分为子类型限定、超类型限定和无限定。通配符不是类型变量,因此不能在代码中使用"?"作为一种类型。
 
子类型限定
表示类型的上界,类似泛型的类型变量限定,格式是:? extends X。
作用:主要用于安全地访问数据,可以访问X及其子类型,并且不能写入非null的数据。
例如:
import java.util.ArrayList;
import java.util.List;
 
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;
for (int i = 0; i < list1.size(); i++) {
A a1 = list1.get(i);
System.out.println(a1);
}
 
//这里如果set任何非null的值如a/b/c,编译器都会报错,因为D<? extends A>可以写入A及其子类,编译器无法确定具体哪个类型
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) {
 
}
}
 
输出:
A{}
B{}
C{}
 
超类型限定
表示类型的下界,格式是:? super X。
特点:
1、限定为X和X的超类型,直至Object类,因为不知道具体是哪个超类型,因此方法返回的类型只能赋给Object。
2、因为X的子类型可以向上转型为X,所以作为方法的参数时,可以传递null,X以及X的子类型
作用:主要用于安全地写入数据,可以写入X及其子类型。
例如:
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。
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;
}
}
有什么作用呢?对于一些简单的操作比如不需要实际类型的方法,就显得比泛型方法简洁。
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> {
}

猜你喜欢

转载自www.cnblogs.com/gjb724332682/p/9285551.html