泛型、泛型上限、泛型下限、泛型通配符
DAY8.1 Java核心基础
泛型
Generics 是指在类定义时不指定类中信息的具体数据类型,而是用一个标识符来代替,当外部实例化对象时再指定具体的数据类型。
在定义类或者接口时不明确指定类中信息的具体数据类型,在实例化时再来指定具体的数据类型
极大地提升了类的扩展性,一个类可以装载各种不同的数据类型
泛型可以指代类中的成员变量数据类型,方法的返回值数据类型以及方法的参数数据类型。
基本使用:
定义一个Demo不指定类中的具体数据类型,用标识符代替
public class Demo<T>{
private T t;
public Demo(T t) {
this.t = t;
}
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
public static void main(String[] args) {
Demo<String> hello = new Demo<>("hello");
System.out.println(hello.getT());
Demo<Integer> integerDemo = new Demo<>(11);
System.out.println(integerDemo.getT());
}
输出:
泛型也可以同时写多个泛型
public class Demo<T,A,B>{
private T t;
private A a;
private B b;
public Demo(T t, A a, B b) {
this.t = t;
this.a = a;
this.b = b;
}
@Override
public String toString() {
return "Demo{" +
"t=" + t +
", a=" + a +
", b=" + b +
'}';
}
}
public static void main(String[] args) {
Demo<String, Integer, Float> hello = new Demo<>("hello", 1, 2.0f);
System.out.println(hello);
}
泛型通配符<?>:在不确定传入的数据类型的时候可以使用通配符
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
test(integers);
ArrayList<String> strings = new ArrayList<>();
test(strings);
}
public static void test(ArrayList<?> list) {
System.out.println(list);
}
比如传入的参数是Interger类型和String类型,如果定义ArrayList list作为形参则String类型的数组无法传递
泛型的上限和下限
上限:类名<? extends A> 这个类型必须是A类的子类或者A类型本身
下限:类名<? super A> 这个类型必须是A类的父类或则A类型本身
public class Test {
public static void main(String[] args) {
ArrayList<Double> doubles = new ArrayList<>();
doubles.add(1.0);
test1(doubles);
ArrayList<Object> strings = new ArrayList<>();
strings.add("hello");
test2(strings);
}
/**
* 标识test1方法的list参数的类型是Number的子类或者是Number本身,比如 Integer、Double、Float...
* @param list
*/
public static void test1(ArrayList<? extends Number> list) {
System.out.println(list);
}
/**
* 表示test2方法的list参数的类型是String的父类或者是String本身,String or Object
* @param list
*/
public static void test2(ArrayList<? super String> list) {
System.out.println(list);
}
}
泛型接口
public interface MyInterface<T> {
public T test();
}
实现类:
public class MyInterfaceImpl1 implements MyInterface<String>{
public String t;
public MyInterfaceImpl1(String t) {
this.t = t;
}
@Override
public String test() {
return t;
}
}
public class MyInterfaceImpl2<T> implements MyInterface<T>{
public T t;
public MyInterfaceImpl2(T t) {
this.t = t;
}
@Override
public T test() {
return t;
}
}
两个实现类,一个在实现的时候就定义了类型,一个没有定义,所以MyInterfaceImpl1就不能在使用的时候指定其它类型对象,就只能使用String类型
正确测试代码:
public static void main(String[] args) {
MyInterfaceImpl1 myInterfaceImpl1 = new MyInterfaceImpl1("123");
System.out.println(myInterfaceImpl1.test());
MyInterfaceImpl2<Integer> myInterfaceImpl2 = new MyInterfaceImpl2<>(123);
System.out.println(myInterfaceImpl2.test());
}