泛型集合的面试题

   

IteratorListIterator有什么区别:

          Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。

Collection和Collections的区别:

          答:Collection:是java.util包中的接口,是集合类的基本接口,主要的子接口有List和Set

Collections:是java.util包中的类,是针对集合的一个实用工具类,它包含了对各种集合的搜索、排序和线程安全等一系列的静态方法。

ArrayList与Vector的异同:

        答:相同点:ArrayList和Vector都是List的子类,都是有序的集合,可以存储相同的元素,相当于动态数组,他们都可以按索引位置取得指定的元素。

        区别:(1)出现的时间:Vector是在JDK1.0就已存在,而ArrayList到了JDK1.2才推出。

(2)同步性:Vector是线程安全的,也就是说它的方法之间是线程同步的,而ArrayList是线程不安全的,它的方法之间是线程不同步的。在程序设计中,如果是只有一个线程会访问到集合,最好选择使用ArrayList,因为他不考虑线程安全,效率会高些;如果多个线程会访问到集合,最好选择使用Vector,因为不需要开发人员自己编写线程安全的代码。

(3)数据增长:ArrayList与Vector都存在初始的容量大小,且都为10,当存储进集合里的元素的个数超过了容量时,就需要增加ArrayList与Vector的存储空间。每次要增加存储空间时,不是只增加一个存储单元,而是增加多个存储单元。这就要求每次增加的存储单元的个数在内存空间利用与线程效率之间要取得一定的平衡。Vector默认增长为原来一倍,而ArrayList的增长策略在文档中没有明确规定(从源代码看到的是增长为原来的一半)

(4)输出方式:Vector可以使用Iterator、foreach和Enumeration方式输出,而ArrayList只能使用Iterator、foreach方式输出

  简述HashMap与Hashtable的异同:

        答:相同点:HashMap与Hashtable都是Map接口的实现类,而HashMap是Hashtable的轻量级实现(非线程安全的实现)。两者都是用key-value方式获取数据。

                  区别:(1)出现的时间:Hashtable在JDK1.0时出现,属于旧的操作类,而HashMap是在JDK1.2时推出的类,属于较新的操作类

(2)同步性:Hashtable是线程安全的,也就是说是同步的,性能相对较低,而HashMap是线程不安全的,不是同步的,性能相对较高。

(3)值:Hashtable不允许存放null值和null键,而HashMap允许存在一个null键和多个null值

(4)HashMap没法保证映射的顺序一直不变,但是作为HashMap的子类LinkedHashMap,如果想要预知的顺序迭代(默认按照插入顺序),你可以很轻易的置换为HashMap,如果使用Hashtable就没那么容易了。

(5)迭代HashMap采用快速失败机制,而Hashtable不是,所以这是设计的考虑点

ArrayList中的浅拷贝与深拷贝:

        浅拷贝:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。  

深拷贝:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍.(eg:  1、直接赋值(字符串外都属于浅拷贝)  2、使用构造函数(深拷贝)  3、使用clone()方法(深拷贝)  )

ArrayList中为何加transient关键字?

             transient是Java语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。这里的对象存储是指,Java的serialization提供的一种持久化对象实例的机制。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。使用情况是:当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。

Java中的泛型是什么 ? 使用泛型的好处是什么?

      泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

Java的泛型是如何工作的 ? 什么是类型擦除

          Java中的泛型基本上都是在编译器这个层次来实现的。在生成的Java字节码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会在编译器在编译的时候去掉。这个过程就称为类型擦除。

请举例说明static和泛型的冲突所在

泛型类确定T的类型实在运行是时期,而static在编译时期已经存在。

常见的10道泛型面试题:

 1. Java中的泛型是什么 ? 使用泛型的好处是什么?

这是在各种Java泛型面试中,一开场你就会被问到的问题中的一个,主要集中在初级和中级面试中。那些拥有Java1.4或更早版本的开发背景的人 都知道,在集合中存储对象并在使用前进行类型转换是多么的不方便。泛型防止了那种情况的发生。它提供了编译期的类型安全,确保你只能把正确类型的对象放入 集合中,避免了在运行时出现ClassCastException。

2. Java的泛型是如何工作的 ? 什么是类型擦除 ?

这是一道更好的泛型面试题。泛型是通过类型擦除来实现的,编译器在编译时擦除了所有类型相关的信息,所以在运行时不存在任何类型相关的信息。例如 List<String>在运行时仅用一个List来表示。这样做的目的,是确保能和Java 5之前的版本开发二进制类库进行兼容。你无法在运行时访问到类型参数,因为编译器已经把泛型类型转换成了原始类型。根据你对这个泛型问题的回答情况,你会 得到一些后续提问,比如为什么泛型是由类型擦除来实现的或者给你展示一些会导致编译器出错的错误泛型代码。请阅读我的Java中泛型是如何工作的来了解更 多信息。

3. 什么是泛型中的限定通配符和非限定通配符 ?

这是另一个非常流行的Java泛型面试题。限定通配符对类型进行了限制。有两种限定通配符,一种是<? extends T>它通过确保类型必须是T的子类来设定类型的上界,另一种是<? super T>它通过确保类型必须是T的父类来设定类型的下界。泛型类型必须用限定内的类型来进行初始化,否则会导致编译错误。另一方面<?>表 示了非限定通配符,因为<?>可以用任意类型来替代。更多信息请参阅我的文章泛型中限定通配符和非限定通配符之间的区别。

4. List<? extends T>和List <? super T>之间有什么区别 ?

这和上一个面试题有联系,有时面试官会用这个问题来评估你对泛型的理解,而不是直接问你什么是限定通配符和非限定通配符。这两个List的声明都是 限定通配符的例子,List<? extends T>可以接受任何继承自T的类型的List,而List<? super T>可以接受任何T的父类构成的List。例如List<? extends Number>可以接受List<Integer>或List<Float>。在本段出现的连接中可以找到更多信息。

5. 如何编写一个泛型方法,让它能接受泛型参数并返回泛型类型?

编写泛型方法并不困难,你需要用泛型类型来替代原始类型,比如使用T, E or K,V等被广泛认可的类型占位符。泛型方法的例子请参阅Java集合类框架。最简单的情况下,一个泛型方法可能会像这样:

public V put(K key, V value) {

return cache.put(key, value);

}

6. Java中如何使用泛型编写带有参数的类?

这是上一道面试题的延伸。面试官可能会要求你用泛型编写一个类型安全的类,而不是编写一个泛型方法。关键仍然是使用泛型类型来代替原始类型,而且要使用JDK中采用的标准占位符。

7. 编写一段泛型程序来实现LRU缓存?

对于喜欢Java编程的人来说这相当于是一次练习。给你个提示,LinkedHashMap可以用来实现固定大小的LRU缓存,当LRU缓存已经满 了的时候,它会把最老的键值对移出缓存。LinkedHashMap提供了一个称为removeEldestEntry()的方法,该方法会被put() 和putAll()调用来删除最老的键值对。当然,如果你已经编写了一个可运行的JUnit测试,你也可以随意编写你自己的实现代码。

8. 你可以把List<String>传递给一个接受List<Object>参数的方法吗?

对任何一个不太熟悉泛型的人来说,这个Java泛型题目看起来令人疑惑,因为乍看起来String是一种Object,所以 List<String>应当可以用在需要List<Object>的地方,但是事实并非如此。真这样做的话会导致编译错误。如 果你再深一步考虑,你会发现Java这样做是有意义的,因为List<Object>可以存储任何类型的对象包括String, Integer等等,而List<String>却只能用来存储Strings。

List<Object> objectList;

List<String> stringList;

objectList = stringList; //compilation error incompatible types

9. Array中可以用泛型吗?

这可能是Java泛型面试题中最简单的一个了,当然前提是你要知道Array事实上并不支持泛型,这也是为什么Joshua Bloch在Effective Java一书中建议使用List来代替Array,因为List可以提供编译期的类型安全保证,而Array却不能。

 

10. 如何阻止Java中的类型未检查的警告? 如果你把泛型和原始类型混合起来使用,例如下列代码,Java 5的javac编译器会产生类型未检查的警告,例如

1
List<String> rawList = 
new
 
ArrayList()

 

2
注意: Hello.java使用了未检查或称为不安全的操作;

这种警告可以使

posted @ 2017-06-20 23:09  lsj91  阅读(423)  评论(0编辑  收藏  举报