关于泛型
来源:互联网 发布:js 触发事件 编辑:程序博客网 时间:2024/05/29 16:14
Java泛型的局限性:基本类型无法作为类型参数,不过Java SE5具备了自动打包和自动拆包的功能。
是否拥有泛型方法,与其所在的类是否是泛型没有关系。
对于一个static的方法而言,无法访问泛型类的类型参数,所以,如果static方法需要使用泛型能力,就必须使其成为泛型方法。
定义泛型方法,只需要将泛型参数列表置于返回值之前。
public <T> void f(T x) { }
当使用泛型类时,必须在创建对象的时候指定类型参数的值,而使用泛型方法的时候,通常不必指明参数类型,因为编译器会为我们找出具体的类型,这称为”类型参数推断”。因此,我们可以向调用普通方法一样调用泛型方法。
类型推断只对赋值操作有效,其他时候并不起作用,如果你将一个泛型方法调用的结果作为参数,传递给另一个方法,这时编译器并不会执行类型推断,在这种情况下,编译器认为,调用泛型方法后,其返回值被赋给一个Object类型的变量。
"ABCDEFGHIJKLMN".split("")
可以将A-N的字符串分开。
注意泛型的类型比较
Class c1 = new ArrayList<String>().getClass()Class c2 = new ArrayList<Integer>().getClass()c1 == c2 //true
Java泛型是使用擦除来实现的,这意味着当你在使用泛型时,任何具体的类型信息都会被擦除,唯一知道的就是你在使用一个对象,因此List<String>
与List<Integer>
在运行上事实上是相同的类型,这两种形式都被擦除成他们的“原生”类型,即List。因此在泛型代码内部,无法获得任何有关泛型参数类型的信息。正式有了擦除这一特性,在运行时无法知道该参数变量可以调用哪些方法,因此就出现了extends关键字,来确定边界。例如:
class Manipulator<T>{private K obj;public Manipulator(T x) {obj = x;}//调用方法出错,Error: cannot find symbol : method f():public void manipulate(){ obj.f() }}
解决这一问题可以用extents关键字:
Class Manipulator<T extends HasF>private T obj;public Manipulator(T x) { obj = x;}public void manipulate() { obj.f()}
边界<T extends HasF>
声明T必须具有类型HasF或从HasF导出的类型。像上例:T擦除到HasF,就好像在类的声明中用HasF替换了T一样。
即使擦除在方法或类内部移除了有关实际类型的信息,编译器仍旧可以确保在方法或类中使用的类型的内部一致性.在传递进来的值进行额外的编译器检查,并插入对传递出去的值得转型,因此:”边界就是发生动作的地方”
擦除丢失了在泛型代码中执行某些操作的能力,任何在运行时需要知道确切类型信息的操作都将无法工作.例如:
public class Erased<T>{ private final int SIZE = 100; public static void f(Object arg){ if(arg instanceof T){} // Error T var = new T(); // Error T[] array = new T[SIZE];// error T[] array = (T)new Object[SIZE] // Unchecked warning }}
看一下这段代码
List<Fruit> flist = new ArrayList<Apple>();//Apple继承Fruit
在看这类问题的时候,真正的问题是应该谈论容器的类型,而不是容器持有的类型,flist的类型是List<Fruit>
apple的类型是List<Apple>
这在类型上就不等价,因此在编译时就会出错,与数组不同,泛型没有内建的协变类型,这是因为数组在语言中是完全定义的,因此可以内建了编译期和运行时的检查,但是在使用泛型时,编译器和运行时系统都不知道你想要的类型做些什么,以及采用什么样的规则.
对比上面的代码
//OKList<? extends Fruit> flist = new ArrayList<Apple>();//Compile Errorflist.add(new Apple());flist.add(new Fruit());flist.add(new Object());
List<? extends Fruit>
可以理解为”任何具有从Fruit继承的类型的列表”,但正是这样的特性导致了add不能添加任何对象,究其原因是应为add的参数类型也是? extends Fruit
,这是一系列的Fruit或其子类,add并不知道是哪一类型的Fruit,这意味着他可以是任何事物,而编译器无法验证”任何事物”的类型安全性.
超类型通配符
写法是<? super MyClass>
,
该句的意思是主要是MyClass或MyClass的子类型都是可以添加的,关于
<? extends MyClass> <? super MyClass> <MyClass>的区别可以看
区别与理解
0 0
- 关于泛型
- 关于泛型
- 关于泛型
- 关于泛型
- 关于泛型
- 关于泛型
- 关于泛型
- 关于泛型的
- 关于泛型
- C# 关于泛型
- 关于泛型Generics
- 关于泛型数组
- 关于泛型
- 关于泛型
- 关于泛型
- 关于泛型擦除
- 关于泛型
- 关于泛型 java
- PHP 实现代码复用的一个方法 traits新特性
- 数据结构(栈,队列,链表,二叉树)
- python 安装模块报错总结
- Attribute "roundWidth" has already been defined
- spark源码阅读笔记RDD(六) RDD的依赖关系
- 关于泛型
- json包含数组如何转换为javabean
- php3.2.3导入一个大数据量的excle到数据库中出现的问题。
- Java多线程编程2--同步锁定--死锁
- 粒子圆圈效果
- GreenDao在eclipse上的配置
- hibernate的核心类和接口
- Java加密技术(二)——对称加密算法DES&AES
- facebook rebound