泛型
写在前头的重点总结
- 泛型程序设计的作用就是让编写的代码可以被不同类型的对象所重用
- 泛型的使用,即在声明类或定义一个泛型方法时加形如<T>的菱形,里面是占位符,这个占位符就指代泛型所包含的所有类型
- 泛型类或方法中的占位符类型如果要加以约束: <T extends Comparable & Serializable>, 而不是用 implements
- 类型擦除:类型擦除之所以产生,是因为对于虚拟机来讲不存在泛型类型对象,而只有普通的类和方法。虚拟机处理时要把泛型类型处理为对应的原始类型,这个过程就叫做类型擦除。
- 为了保持多态特性,类型擦除可能会产生一些错误,因此使用Java泛型时要考虑一些限制:
- 不能用基本类型实例化类型参数,如 不能用double而要用Double,因为擦除后的Object域不能存储double值
- 运行时类型查询只适用于原始类型
- 不能创建参数化类型的数组,如Pair<String>[] table = new Pair<String>[10]; 唯一的安全且有效的方法是使用ArrayList:ArrayList<Pair<String>>
- 不能实例化类型变量,即不能使用new T(...), new T[...] 或T.class这样的表达式中的类型变量
- 不能构造泛型数组
- 禁止使用带有类型 变量的静态域或静态方法
- 不能抛出或捕获泛型类的实例
- 通配符—— ?:另一种为泛型变量类型施加约束的方法,如public static void printBuddies( Pair<? extends Employee>),这个方法, 则可以将Pair<Manager> (Manager继承Employee)作为参数传入该方法。
- 如果反射的对象是泛型类的实例,那么通过反射方法并不能得到太多关于泛型类型参数的信息。
详细内容
https://www.cnblogs.com/dyj-blog/p/8990050.html
集合
- Java集合类库将接口与实现分离,如队列Queue接口的实现方式有两种:如果需要一个循环数组队列,就可以使用ArrayDeque类;如果需要使用一个链表队列,就直接使用LinkedList类,该类实现了Queue接口。在构建对应的集合对象时,只有使用具体的类才有意义,否则就不知道究竟使用了哪种具体实现。
Queue<Customer> expressLane = new ArrayDeque<>(100); expressLane.add(new Customer("Harry")); //利用这种方式,一旦改变了想法,可以轻松使用另外一种不同的实现,即修改调用构造器之处 Queue<Customer> expressLane = new LinkedList<>(); expressLane.add(new Customer("Henry")); //本文下面涉及到的两行代码 List<String> staff = new LinkedList<>();
不同实现方式的效率也是不同的,比如循环数组队列比链表更高效,但是它是一个有界集合,即容量有限。如果程序中要收集的对象数量没有上限,就最好使用链表来实现。
- Java类库中集合类的基本接口是Collection接口,该接口有一些基本方法,例如: boolean add(E element);以及 Iterator<E> iterator(); 其中iterator方法用于返回一个实现了Iterator接口的对象,即迭代器,用来访问集合中的每一个 元素。
- 应该将Java迭代器认为是位于两个元素之间,当调用next()时,迭代器就越过下一个元素,并返回刚刚越过的元素的 引用。一个有用的推论是,可以将Iterator.next()与InputStream.read()看作等效的。 另外,Iterator的next()方法和remove()方法的调用具有依赖性,调用remove()方法之前必须调用next()方法,这样就会删掉刚刚next()方法所越过的元素。对于LinkedList来说,它实现了一个Iterator接口的子接口ListIterator接口,该接口多一个与next()方法相对的previous()方法,可以用来反向遍历与删除元素。
import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; public class JavaSetsTest