Java SE面试题(2)含List集合

1. 请说明一下final, finally, finalize的区别。

final用来声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。

finally是异常处理语句结构中的一部分,表示总是执行。

finally时Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾垃圾收集时的其它资源回收,例如关闭文件等。

2. 请说明Comparable和Comparator接口的作用以及它们的区别。

Comparable和Comparator接口是用来对自定义的class比较大小的。
Comparator和 Comparable的区别:

Comparator定义在Person的外部
Comparable定义在Person的内部

public class Persion implements Comparable {..比较Person的大小..},

接口提供compareTo()方法,因为已经实现了比较器,那么Person现在是一个可以比较大小的对象了,它的比较功能和String完全一样,可以随时随地的拿来比较大小,因为Person现在自身就是有大小之分的。Collections.sort(personList)可以得到正确的结果。

Comparator是定义在Person的外部的,此时Person类的结构不需要有任何变化,如

public class Person{ String name; int age }

然后另外定义一个比较器:

public PersonComparator implements Comparator() {
    ..比较Person的大小..
}

,接口有compare()和equals()两个方法,在PersonComparator里面实现了怎么比较两个Person的大小. 所以用这种方法,要对一个 personList进行排序的时候除了要传递personList过去,还需要把PersonComparator传递过去,因为怎么比较Person的大小是在PersonComparator里面实现的,如Collections.sort( personList , new PersonComparator() )

3. 接口和抽象类的区别是什么?

  1. 抽象类要被子类继承,接口要被类实现。
  2. 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。
  3. 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  4. 接口是设计的结果,抽象类是重构的结果。
  5. 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
  6. 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
  7. 抽象类主要用来抽象类别,接口主要用来抽象功能。

4. 请你谈谈如何通过反射创建对象?

  • 方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
  • 方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");

5. 什么是泛型

泛型:就是一种不确定的数据类型。
比如:ArrayList E就是泛型。 这种不确定的数据类型需要在使用这个类的时候才能够确定出来。
泛型可以省略,如果省略,默认泛型是Object类型。
泛型的好处:

  1. 省略了强转的代码。
  2. 可以把运行时的问题提前到编译时期。

6. 请你解释一下类加载机制,双亲委派模型,好处是什么?

虚拟机类加载机制:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型。
类从被加载到JVM中开始,到卸载为止,整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。

类加载机制

其中类加载过程包括加载、验证、准备、解析和初始化五个阶段。

双亲委派模型

某个特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,依次递归,如果父类加载器可以完成类加载任务,就成功返回;只有父类加载器无法完成此加载任务时,才自己去加载

使用双亲委派模型的好处在于Java类随着它的类加载器一起具备了一种带有优先级的层次关系

7. 请你谈谈StringBuffer和StringBuilder有什么区别,底层实现上呢?

StringBuffer线程安全,StringBuilder线程不安全,底层实现上的话,StringBuffer其实就是比StringBuilder多了Synchronized修饰符。

8. 请列举你所知道的Object类的方法并简要说明。

  1. Object()默认构造方法。
  2. clone() 创建并返回此对象的一个副本。
  3. equals(Object obj) 指示某个其他对象是否与此对象“相等”。
  4. finalize()当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
  5. getClass()返回一个对象的运行时类。
  6. hashCode()返回该对象的哈希码值。
  7. notify()唤醒在此对象监视器上等待的单个线程。
  8. notifyAll()唤醒在此对象监视器上等待的所有线程。toString()返回该对象的字符串表示。
  9. wait()导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
  10. wait(long timeout)导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
  11. wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

9. 阐述ArrayList、Vector、LinkedList的存储性能和特性


Java 的 List 是非常常用的数据类型。List 是有序的 Collection。Java List 一共三个实现类:分别是 ArrayList、Vector 和 LinkedList。

ArrayList LinkedList Vector
底层实现 数组 双向循环链表 数组
同步性及效率 不同步,非线程安全,效率高 不同步,非线程安全,效率高 同步,线程安全,效率低
特点 查询快,增删慢 查询慢,增删快 查询快,增删慢
默认容量 10 / 10
扩容机制 int newCapacity = oldCapacity + (oldCapacity >> 1); //1.5 倍 / 2 倍

ArrayList(数组)

ArrayList 是最常用的 List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。当从 ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。

Vector ( 数组实现、 线程同步)

Vector 与 ArrayList 一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写 Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问 ArrayList 慢。

LinkList(链表)

LinkedList 是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了 List 接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

由于ArrayList和LinkedListed都是非线程安全的,如果遇到多个线程操作同一个容器的场景,则可以通过工具类Collections中的synchronizedList方法将其转换成线程安全的容器后再使用(这是对装潢模式的应用,将已有对象传入另一个类的构造器中创建新的对象来增强实现)。

10. 请你说说Iterator和ListIterator的区别?

  • Iterator可用来遍历Set和List集合,但是ListIterator只能用来遍历List。
  • Iterator对集合只能是前向遍历,ListIterator既可以前向也可以后向。
  • ListIterator实现了Iterator接口,并包含其他的功能,比如:增加元素,替换元素,获取前一个和后一个元素的索引,等等。

11. 请简单说明一下什么是迭代器

  • Iterator提供了统一遍历操作集合元素的统一接口, Collection接口实现Iterable接口
  • 每个集合都通过实现Iterable接口中iterator()方法返回Iterator接口的实例, 然后对集合的元素进行迭代操作.
  • 有一点需要注意的是:在迭代元素的时候不能通过集合的方法删除元素, 否则会抛出ConcurrentModificationException 异常. 但是可以通过Iterator接口中的remove()方法进行删除.

12. 请你说明一下TreeMap的底层实现?

TreeMap的实现就是红黑树数据结构,也就是说是一棵自平衡的排序二叉树,这样就可以保证当需要快速检索时指定节点。

红黑树的插入、删除、遍历时间复杂度都为O(lgN),所以性能上低于哈希表。但是哈希表无法提供键值对的有序输出,红黑树是因为排序插入的,可以按照键值的大小有序输出。

红黑树的性质:

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点永远是黑色的。
  3. 所有的叶节点都是空节点(即null),并且是黑色。
  4. 每个红色节点的两个子节点都是黑色。(每个叶子到根的路径上不会有两个连续的红色节点)
  5. 从任意节点到其子树中每个叶子节点的路径都包含相通数量的黑色节点。

你可能感兴趣的:(Java SE面试题(2)含List集合)