Java中关于单例模式的10个面试问题

来源:互联网 发布:四川广电网络怎么缴费 编辑:程序博客网 时间:2024/06/05 16:00

http://blog.csdn.net/hintcnuie/article/details/17968261


单例模式是最常见的一个模式,在Java中单例模式被大量的使用。这同样也是我在面试时最喜欢提到的一个面试问题,然后在面试者回答后可以进一步挖掘其细节,这不仅检查了关于单例模式的相关知识,同时也检查了面试者的编码水平、多线程方面的知识,这些在实际的工作中非常重要。

在这个简单的Java面试教程中,我列举了一些Java面试过程中关于单例模式的常会被提到的问题。关于这些面试问题,我没有提供答案,因为你通过百度搜索很容易找到这些答案。

那么问题就从什么是单例模式?你之前用过单例模式吗?开始

单例是在整个应用中只有一个实例的类,然后提供getInstance()方法来访问该单例实例。

1) 哪些类是单例模式的候选类?在Java中哪些类会成为单例?

Which classes are candidates of Singleton? Which kind of class do you make Singleton in Java?

这里它们将检查面试者是否有对使用单例模式有足够的使用经验。他是否熟悉单例模式的优点和缺点。

2)你能在Java中编写单例里的getInstance()的代码?

很多面试者都在这里失败。然而如果不能编写出这个代码,那么后续的很多问题都不能被提及。

3)在getInstance()方法上同步有优势还是仅同步必要的块更优优势?你更喜欢哪个方式?

这确实是一个非常好的问题,我几乎每次都会提该问题,用于检查面试者是否会考虑由于锁定带来的性能开销。因为锁定仅仅在创建实例时才有意义,然后其他时候实例仅仅是只读访问的,因此只同步必要的块的性能更优,并且是更好的选择。

4)什么是单例模式的延迟加载或早期加载?你如何实现它?

这是和Java中类加载的载入和性能开销的理解的又一个非常好的问题。我面试过的大部分面试者对此并不熟悉,但是最好理解这个概念。

5) Java平台中的单例模式的实例有哪些?

这是个完全开放的问题,如果你了解JDK中的单例类,请共享给我。

6) 单例模式的两次检查锁是什么?

What is double checked locking in Singleton?

One of the most hyped question on Singleton and really demands complete understanding to get it right because of Java Memory model caveat prior to Java 5. If a guy comes up with a solution of using volatile instance of Singleton then it really shows it has in depth knowledge of Java memory model and he is constantly updating his Java knowledge.

7)你如何阻止使用clone()方法创建单例实例的另一个实例?

该类型问题有时候会通过如何破坏单例或什么时候Java中的单例模式不是单例来被问及。

在JAVA里要注意的是,所有的类都默认的继承自Object,所以都有一个clone方法。为保证只有一个实例,要把这个口堵上。有两个方面,一个是单例类一定要是final的,这样用户就不能继承它了。另外,如果单例类是继承于其它类的,还要override它的clone方法,让它抛出异常。


8)如果阻止通过使用反射来创建单例类的另一个实例?

开放的问题。在我的理解中,从构造方法中抛出异常可能是一个选项。

  通过反射创建单例类的另一个实例:

  如果借助AccessibleObject.setAccessible方法,通过反射机制调用私有构造器,反射攻击:   

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public final class HelloWorld  
  2. {  
  3. private static HelloWorld instance = null;  
  4.    
  5. private HelloWorld()  
  6. {  
  7. }  
  8.    
  9. public static HelloWorld getInstance()  
  10. {  
  11. if (instance == null)  
  12. {  
  13. instance = new HelloWorld();  
  14. }  
  15. return instance;  
  16. }  
  17.    
  18. public void sayHello()  
  19. {  
  20. System.out.println("hello world!!");  
  21. }  
  22.    
  23. public static void sayHello2()  
  24. {  
  25. System.out.println("hello world 222 !!");  
  26. }  
  27.    
  28. static class Test  
  29. {  
  30. public static void main(String[] args) throws Exception  
  31. {  
  32. try  
  33. {  
  34. Class class1 = Class.forName("HelloWorld");  
  35. Constructor[] constructors = class1.getDeclaredConstructors();  
  36. AccessibleObject.setAccessible(constructors, true);  
  37. for (Constructor con : constructors)  
  38. {  
  39. if (con.isAccessible())  
  40. {  
  41. Object classObject = con.newInstance();  
  42. Method method = class1.getMethod("sayHello");  
  43. method.invoke(classObject);  
  44. }  
  45. }  
  46.    
  47. }  
  48. catch (Exception e)  
  49. {  
  50. e.printStackTrace();  
  51. }  
  52. }  
  53. }  
  54. }  
0 0