Java泛型
老规矩,测试一下,下面的程序能否正常运行?为什么?
开头测试题
泛型就是实现了参数化类型,也就是代码可以适用于多种类型。泛型是在编译期检查的,在编译期检查类型是否安全。我认为泛型最有用的就是和集合类一起使用。
简单实现一个泛型类型
定义一个类Holder,T可以理解为一个占位符。使用时可以指定T为其他对象,就像测试代码一样,我们可以用String替换T。
一个泛型的例子
泛型类和泛型接口
上面的那个例子就是泛型类,泛型也适用于接口,我们自定义接口Gen的参数化为T,因为T类型是没办法创建实例的,这里传入Class对象,通过反射来实例化。
泛型接口
泛型方法
静态的方法无法使用类的类型参数,如果静态方法使用泛型的能力,就必须使用泛型方法(非静态的方法也可以为泛型方法)。泛型方法在返回值前定义泛型参数,大概的定义如下:
public void test(T t){}
并且泛型方法可以用在可变参数中,请判断下面的程序到底执行了那个方法?
泛型和可变参数
上面的程序是不能通过编译的,错误信息为:The method test(Integer) is ambiguous for the type TestG。因为在编译时test(T t)和test(Integer t)此时是一样的,我们的参数是Integer的时候,编译器区分不开到底调用哪个方法。
通配符
有时候不限制类型的时候,我们可以用通配符“?”,比如定一个一个List>,这个和不限制好像没有什么区别,当在map中使用的时候就能看出来有一定的用处。比如我们限制key是String类型的,value可以是任意类型的时候,我们可以用Map。
通配符使用的时候可以设置边界,关键字就是entends,语法就是,就是限制参数为某个类型的子类。比如MyClazz exnteds Number>代表MyClazz只能使用Number或者Number的子类。
看一个List中使用通配符的边界的问题,源码如下:
list添加数据问题
Integer是继承于Number,按说能添加才对吧,为什么添加不了了?原因就是add方法的参数是E,当我们使用? extends Number的时候,此时的add方法的参数就变成了了? extends Number,此时编译器不能确定使用的是哪个子类,因此编译器就直接拒绝对参数列表中涉及通配符的方法的调用。
解决这个问题的方法就是使用超类通配符,语法为 super 基类型>,意思声明通配符是由某个特定类的任何基类来界定,修改的代码如下:
超类通配符
总结下问题
1、基本类型不能作为类型参数
2、一个类不能实现同一个泛型接口的两种变体,简单来说就是继承的类和实现的接口的类型参数不同
3、使用带有泛型参数的转型或者instanceof不会有任何效果。
4、如果有两个类型参数的时候,重载时有问题的,代码如下:
重载问题
还是开头的那句话,泛型主要用在集合类中,我们起码要在集合中使用好泛型。
欢迎关注,留言,讨论,如果有任何问题,请批评指正,谢谢!