之前介绍集合时,可以看到有List<String>这样的写法,那么尖括号里的内容是什么呢?这是泛型,意思就是说声明的这个List集合只能存放String类型的元素。
泛型是什么?
‘泛’指一般、不深入,在这里可以认为是不确定、可变的意思,java中允许定义一些不确定的类型,不可以是基本数据类型,但是在编译时期一定要给与这些不确定类型一个确定的类型,这就是泛型,使用泛型可以提高代码复用的效率。之前听过一个小故事,两个项目经理争论接口中方法应该返回什么类型才合适,争论好久都没有结果,这时架构师过来说了句:“用泛型”,使得问题迎刃而解。泛型在java编程中还是很重要的。
为什么要用泛型?
一切为了方便和提高效率。当不确定要选择何种类型时可以使用泛型,当使用到时再确定类型即可,另外使用泛型可以使得接口复用率提高,例如:List集合,List用到了泛型:List<E>,这样便可以使得集合可以任意存储各个类型的对象,使得List接口高度复用,可以假设一个场景,如果List没有使用泛型,那么集合中存储的数据就会五花八门,非常混乱,如果每存储一种类型就去创建一个对应的List集合类,那么这是不可能的,而使用了泛型则这些问题统统被优雅的解决了。
泛型的特性?
一定要知道泛型只能在编译时期使用,并且一定要在程序运行之前给予泛型类型一个确定的类型。
泛型怎么用?
泛型可以在接口、类和方法上使用,用于标记一个不确定的参数类型。接下来使用代码来介绍泛型如何使用:
泛型接口和泛型类的使用(实例化时最好时确定类型):
package com.czp.generic;
//可以这样实现,此时实现类上必须也要加上泛型
public class SelfInterfaceImpl<T> implements SelfInterface<T>{T t;@Overridepublic T getObject(int i) {return t;}
}class Test{public static void main(String[] args) {//当创建带有泛型参数的对象时,如果还不确定泛型的具体类型,则一概为Object类型;实例化时一定要确定类型SelfInterface selfInterface = new SelfInterfaceImpl<>();Object object = selfInterface.getObject(1);//返回为Object型//确定泛型类型为StringSelfInterface<String> selfInterface2 = new SelfInterfaceImpl<>();String string = selfInterface2.getObject(1);//返回为定义的类型//确定泛型类型为IntegerSelfInterface<Integer> selfInterface3 = new SelfInterfaceImpl<>();Integer integer = selfInterface3.getObject(1);//返回为定义的类型}}
泛型方法的使用:
public class SelfMethodTest {public static void main(String[] args) throws InstantiationException, IllegalAccessException {SelfMethodTest test = new SelfMethodTest();Object name = test.getName(ArrayList.class);String []s = {"111","222","333","444"};test.showThings(s);}//使用<T>来定义泛型方法//这里想来想去也只有反射这里用的泛型方法比较好,根据传入的运行时类对象确定类public <T> T getName(Class c) throws InstantiationException, IllegalAccessException {T t = (T)c.newInstance();if (t.getClass().isAssignableFrom(ArrayList.class)) {System.out.println("类型符合");}return t;}//这里顺便说一下可变参数,当传入的形参太多时,则可以使用一个数组进行传参,但是呢,样式做了改变 int ...i 表示的是传入一个int类型的数组i作为形参//有的时候不能确定参数的类型,可以使用泛型,如下public void showThings(int ...i) {}//此时是泛型数组,所以传参数时,数组一定要确定类型public <T> void showThings(T ...t) {for (T tt : t) {System.out.println(tt);}}
}
有的时候会看到如下这种方式的泛型的表示:
public void showThings(List<?> list)
public void showThings(List<? extends Map> list)
那么这里的问号是什么呢?我们把问号叫做通配符。List<?> list 表示可以接受任何类型的List集合,而List<? extends Map> list 则表示只能接受继承或者实现了了Map接口的接口或类。有的时候就是想要限制传入的参数的类型,例如:我就想接受一个Map或者Map扩展类的参数,其余的不想接收,这时候就可以使用<? extends Map>这种形式进行声明;还有一种时<? super Map> ,他表示的是必须是Map或者Map的父级接口类型。