关于java:15个问题告诉你如何使用Java泛型

7次阅读

共计 3421 个字符,预计需要花费 9 分钟才能阅读完成。

摘要:Java 泛型其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型能够用在类、接口和办法的创立中,别离称为泛型类、泛型接口、泛型办法。

本文分享自华为云社区《15 个问题把握 java 泛型》,原文作者:breakDraw。

Java 泛型是 J2 SE1.5 中引入的一个新个性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型能够用在类、接口和办法的创立中,别离称为泛型类、泛型接口、泛型办法。

泛型办法

个别定义如下,即办法的后面加了个 <T>

public class FTest {public <T> List<T> f(T t){...};
}

三种泛型参数推断形式:

1、间接在 f()后面加确定泛型

fTest.<Integer>f(xxx)
2、通过输出参数确定,上面这个推断为 Integer

int number = 0;
fTest.f(number)

3、可通过 返回值 确定

List<Integer> list = fTest.f(xxx);
Q: 上面这段代码哪里有问题?是 toString()那里吗?

public class A<T> {public static void  test(T t){System.out.println(t.toString());  
  }
}

A:test 是 static 办法,因而无奈感知 A <T> 实例里的 T
须要改成
public static <T> void test(T t)

toString()那里没问题,toString 就是 Object 的办法。

泛型参数和类型打消

Q:泛型参数 T 在运行时,会变成什么?
A:对立变成 Object 且不蕴含任何类型信息。

Q: 泛型参数 T 能够能够应用 instanceof 做比拟吗?

class A<T> {void f(Object arg)
   if(arg instanceof T) {...}
}

A: 不能,编译器会报错。

Q:泛型参数 T 能够进行 new T()或者 new T[]操作吗?
A:不能,编译器会报错。

Q:能调用泛型参数对象里的办法吗?

T.f();
A:只能调用 Object 的办法。

Q:能够用 T 做强制转化吗?

T t = (T)object;
A: 能运行,但不会真正产生转型,编译时会触发 waring 正告。

新建泛型对象时的问题

先假设有 2 个类,基类 Parent 和子类 Child

class Parent{}
class Child extends Parent{}

答复以下问题:
Q:上面这句话有问题吗?

List<Parent> list = new ArrayList<Child>()

A:有问题,编译就谬误了。List<Parent> 和 ArrayList<Child> 并不存在父子类的关系

Q:

List<? extends Parent> list = new ArrayList<Child>();

这个 list 有什么特点?

A:这个 list 能够调用 A a = list.get(),然而不能 list.add(new Parent())

  • 起因:
    list.get()所做的操作是在返回时,把外部的 <? extend Parent> 强转成 Parent,是正当的,任何 Parent 的子类都能够转成 Parent
    list.add(new Parent())所做的操作是在输出时,把内部的 A 转成外部的 <? extend Parent>,这是不合理的,因为咱们不晓得这个 Parent 对象能够转成哪个 Parent 的子类。
    Q:
List<? super Child> list = new ArrayList<Parent>();

这个 list 有什么特点?
上面谁会报错

list.add(new Child())
list.add(new Parent())
Parent a= list.get();
Child b = list.get()

A:截图如下:

  • Child c = list.get() 或者 Parent p = list.get()所做的操作是在返回时,把外部的 <? super Child> 强转成内部的 Parent 或者 child,是不合理的,因为编译器感觉 child 的父类 不肯定 能转成 parent 或者 child,所以禁止了这种行为(比方 parent 的父类是 object,但 object 不肯定就能转成 parent 或者 child)。*list.add(new Child())所做的操作是在输出时,把内部的 child 或者 parent 转成外部的 <? super Child>,这是正当的,因为 child 和 parent 肯定能转成 child 的父类。

Q:

List<?> list = new ArrayList<A>();
这个 list 有什么特点?

A:get 和 add 都不行,只能做 remove 等无返回值无输出 A 的操作。
PS:留神,不是说不能调用 get 或 add 办法,而是调用 get 或 add 时,不能应用 A 这个对象去操作。
即无奈做 add(A) 或者 A a = get(0)
然而能够做 add(object) 或者 Object o = get(0)
因为?能够转为 Object,然而无奈转为 A。

Q:上面这个代码会报错吗?

   List<Fruit> fruitList = new ArrayList<>();
   fruitList.add(new Fruit());
   List<Apple> appleList = new ArrayList<>();
   appleList.add(new Apple());
   fruitList.addAll(appleList);
   System.out.println(fruitList);

A: 不会报错。会失常打印后果。

PECS 准则
留神 PECS 准则和下面的区别!
下面之前提到的? extend 或者? supert,都是在申明对象的时候用的。
而 PECS 准则是用于泛型对象的办法输出参数!

假如有一个类定义如下:

public static class MyList<T> {List<T> list = new ArrayList<>();

    // 把输出参数塞给本人,相似于生产操作
    public void pushList(List<T> t) {list.addAll(t);
    }

    // 把本人的内容塞给输出参数,相似于让输出参数做生产。public void pollList(List<T> t) {t.addAll(list);
    }
}

则 T 就是泛型参数。

Q:上面代码能失常运行吗?

MyList<Number> myList = new MyList<>();

List<Integer> intList = new ArrayList<>();
myList.pushList(intList);

List<Object> objectList = new ArrayList<>();
myList.pollList(objectList);

A: 不能失常运行,pushList 和 pollList 都会报错

因为编译器查看后,认为 List<Integer> 和 List<Number> 不是一个货色!

Q:如果上文要反对 pushList,应该怎么批改 pushList 办法的定义?
A:改成这样:

// 把输出参数塞给本人,相似于生产操作
public void pushList(List<? extends T> t) {list.addAll(t);
}

即编译器认为,List<Integer> 和 List<? extend Number> 是一个货色,容许!

Q:如果要反对 pollList,怎么批改定义?
A:

// 把本人的内容塞给输出参数,相似于让输出参数做生产。public void pollList(List<? super T> t) {t.addAll(list);
}

因为是把本人的货色塞给输出参数,而想要能塞进去,必须保障本人这个 T,是输出参数的子类,反过来说,输出参数必须是 T 的父类,所以用 super
于是编译器认为,List<Object> 和 List<? super Number> 是一个货色,容许!

PECS 准则出自 Effective Java,留神只是一个编程倡议而已!

  • 如果有一个类 A,泛型参数为 T
  • 如果他个别只用于接管输出容器 List 后,塞入本人外部的 T 容器,则类 A 就叫生产者,因而输出参数最好定义为 <? extend T> 最好,以便能接管任何 T 子类的容器。
  • 如果他个别只用于接管输出容器后 List,把本人外部的 T 元素塞给它,那么这个类 A 就叫消费者,输出参数最好定义为 <? super T>\ 最好,以便本人的 T 元素能塞给任何 T 元素的父类容器。

点击关注,第一工夫理解华为云陈腐技术~

正文完
 0