1 泛型入门
集合元素过去默认为Object类型,无法指定元素类型,编译时不检查类型,而且每次取出对象都要进行强制类型转换,泛型出现避免了这种臃肿的代码。下列代码会看到编译时不检查元素类型导致的异常。
public class ListErr { public static void main(String[] args) { List strList = new ArrayList(); strList.add("人有悲欢离合"); strList.add("月有阴晴圆缺"); strList.add(23333); //ClassCastException strList.forEach(str -> System.out.println(((String) str).length())); } }
泛型用于指定集合存储数据的类型。
List<String> books=new ArrayList<String>();
上述代码定义集合时使用泛型,创建对象时构造器也给出泛型类型,这样显然是多余的。java7做了改进。
List<String> books=new ArrayList<>();
2 深入泛型
- 2.1定义泛型接口、类
我们可以在定义一个类时允许它使用泛型,通过阅读java提供的集合接口源码可以知道如何定义泛型接口。
//定义接口时指定了一个类型形参E public interface List<E> extends Collection<E> { //在接口中将形参E作为类型使用 boolean add(E e); Iterator<E> itorator; // ... }
在实际使用时,只需要在声明对象时传入E的实参即可 。
- 2.2 从泛型类派生子类
从泛型类派生子类时,我们可以为泛型指定实参,也可以不使用,注意不要再使用形参T。
public class Apple<T> { private T info; public T getInfo(){ return this.info; } } public class SmallApple extends Apple<String> { private String info; public String getInfo() { return this.info; } }
2.3 并不存在泛型类
实际上,泛型只是设计来用于方便编程,并不会由于指定类型不同而生成不同的class文件。
public class GenericTest {
public static void main(String[] args) { List<String> strList = new ArrayList<>(); List<Integer> intList = new ArrayList<>(); // true System.out.println(strList.getClass() == intList.getClass()); }
}
也就是说,不管传入实参是不是一个类型,它们仍然被当成一个类型的数据,不允许在静态成员中使用泛型形参。