一、 泛型
1 概述
Java泛型在J2 SE 1.5中引入,本质是参数化类型”。就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。 这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
1.1 泛型类
/**
* 泛型类
*/
//
public class ClassName<T> {
private T data;
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
1.2 泛型接口
/**
* 泛型接口
*/
public interface IntercaceName<T>{
T getData();
}
1.2.1 泛型接口实现
//指定类型
public class Interface1 implements IntercaceName<String> {
private String text;
@Override
public String getData() {
return text;
}
}
//不指定类型
public class Interface1<T> implements IntercaceName<T> {
private T data;
@Override
public T getData() {
return data;
}
}
1.3 泛型方法
private static <T> T methodName(T a, T b) {}
1.4 泛型限制类型
在使用泛型时,可以指定泛型的限定区域,比如必须是某个类的实现类,格式:
<T extends 类或接口1 & 接口2>
1.5 泛型中的通配符
类型通配符是使用 ?代替方法具体的类型实参。
- <? extends Parent>指定了泛型类型的上届
- <? super Child>指定了泛型类型的上届
- <?>指定了泛型类型的上届
1.6 作用
(1)泛化 (2)类型安全 (3)消除强制类型转换 (4)向后兼容
提高代码复用率;泛型中的类型在使用时指定,不需要强制类型转换(类型安全,编译器会检查类型)
类型安全: 泛型的主要目标是提高Java程序的类型安全。通过知道使用泛型定义的变量的类型限制,编译器可以在非常高的层次上验证类型假设。没有泛型,这些假设就只存在于系统开发人员的头脑中。 通过在变量声明中捕获这一附加的类型信息,泛型允许编译器实施这些附加的类型约束。类型错误就可以在编译时被捕获了,而不是在运行时当作ClassCastException展示出来。将类型检查从运行时挪到编译时有助于Java开发人员更早、更容易地找到错误,并可提高程序的可靠性。
消除强制类型转换: 泛型的一个附带好处是,消除源代码中的许多强制类型转换。这使得代码更加可读,并且减少了出错机会。尽管减少强制类型转换可以提高使用泛型类的代码的累赞程度,但是声明泛型变量时却会带来相应的累赞程度。在简单的程序中使用一次泛型变量不会降低代码累赞程度。但是对于多次使用泛型变量的大型程序来说,则可以累积起来降低累赞程度。所以泛型消除了强制类型转换之后,会使得代码加清晰和筒洁。
泛型的运行效率:在非泛型编程中,将筒单类型作为Object传递时会引起Boxing(装箱)和Unboxing(拆箱)操作,这两个过程都是具有很大开销。引入泛型后,就不必进行Boxing和Unboxing操作了,所以运行效率相对较高,特别在对集合操作非常频繁的系统中,这个特点带来的性能提升更加明显。
1.7 注意
- 在编译之后程序会采取去泛型化的措施。
- Java中的泛型,只在编译阶段有效。
- 在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加。
- 类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。
- 不要在泛型类中定义equals(Tx)这类方法,因为Object类中也有equals方法,当泛型类被擦除后,这两个方法会冲突。
1.8 泛型擦除
在编译期间,所有的泛型信息都会被擦除掉。
/**
* 泛型擦除
*/
public class Test {
public static void main(String[] args) {
ArrayList<String> arrayList1=new ArrayList<String>();
arrayList1.add("abc");
ArrayList<Integer> arrayList2=new ArrayList<Integer>();
arrayList2.add(123);
System.out.println(arrayList1.getClass()==arrayList2.getClass()); //结果为true
}
}
伪泛型问题,并不像C++的模板那样
看到一篇博客,有所体会,在此贴出链接
泛型的内部原理:类型擦除以及类型擦除带来的问题