答案是不能。
事實證明,在類內部一直實例化自身會造成棧溢出,測試代碼如下。
1 public class test1 { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 test1.A aa = new test1().new A(); 9 test1.A b = aa.getA(); 10 System.out.println("ok"); 11 } 12 13 class A{ 14 15 private A a = new A(); 16 17 public A getA(){ 18 19 return a; 20 } 21 } 22 }
結果:
1 exception in thread "main" java.lang.StackOverflowError 2 at test1$A.<init>(test1.java:13) 3 at test1$A.<init>(test1.java:15) 4 at test1$A.<init>(test1.java:15) 5 at test1$A.<init>(test1.java:15) 6 at test1$A.<init>(test1.java:15) 7 at test1$A.<init>(test1.java:15) 8 at test1$A.<init>(test1.java:15) 9 at test1$A.<init>(test1.java:15) 10 at test1$A.<init>(test1.java:15)
但是如下的代碼為何能夠良好運行?
1 public class test1 { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 test1.A aa = new test1().new A(); 9 test1.A b = aa.getA(); 10 System.out.println("ok"); 11 } 12 13 class A{ 14 15 private A a; 16 17 public A getA(){ 18 a = new A(); 19 return a; 20 } 21 } 22 }
這是因為,聲明類,可以認為是在類內放一張空白紙,實例化是按照圖紙造了一座房子,類內聲明自己,只是放了一張A類型的圖紙,並沒有造房子,不會引起無限調用。
在函數中實例化類,必須調用函數才會執行,因此也不會引起無限調用,所以不會出現錯誤。
由此,還可以實現單例模式。
單例模式分為懶漢式和餓漢式
懶漢式:
1 public class test1 { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 test1.A aa = new test1().new A(); 9 test1.A b = aa.getA(); 10 System.out.println("ok"); 11 } 12 13 class A{ 14 15 private A a = null; 16 17 public A getA(){ 18 if(a == null) 19 a = new A(); 20 return a; 21 } 22 } 23 }
餓漢式:
1 public class test1 { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 // TODO Auto-generated method stub 8 test1.A aa = new test1().new A(); 9 test1.A b = aa.getA(); 10 System.out.println("ok"); 11 } 12 13 class A{ 14 15 private A a = new A(); 16 17 public A getA(){ 18 return a; 19 } 20 } 21 }
懶漢式容易線成不安全,餓漢式加載占內存