主題:Java的內部類——你知道多少?
我在寫這篇文章之前,我對Java內部類也不是很清楚,只知道簡單的應用。前幾天有個朋友問我怎么理解Java內部類,我當時就有點傻了,想了半天也沒有說出來,我想,如果讓大家來回答這個問題,大家該怎么回答呢?我估計,總有一些人回答不上來的,或者說回答的不夠完整。我特意查了查,自己又總結了總結,在這給大家分享一下。 在說之前,我先列出幾個問題:
1.外部類(非主類)通過怎樣的方式訪問內部類?
2.內部類能不能訪問主類私有的屬性,為什么?
3.內部類能不能繼承別的類和接口?
4.內部類能不能是static的?
5.在主類的方法里面可不可以定義內部類?
6.初始化主類的時候是不是也把內部類給初始化了?為什么?
7.怎樣寫一個匿名的內部類?
我目前想到的就這些,在我給大家陳述之前,希望大家好好想想,再往下看:
第一個問題:外部類是怎樣引用內部類的?這個問題,我想,可能有的人就會這樣寫:
這是內部類:InnerClass.
1 public class MainClass {
2
3 public class InnerClass{
4 public String name = "name";
5
6 public String getName() {
7 return name;
8 }
9
10 public void setName(String name) {
11 this.name = name;
12 }
13 }
14 }
以下是引用:
1 public class CheckClass {
2 public static void main(String[] args) {
3 InnerClass innerClass = new InnerClass();
4 System.out.println(innerClass.getName());
5 }
6 }
如果這樣寫的話,會報編譯錯誤。那么為什么會報錯呢?因為在Java的設計中,如果想訪問一個類的內部類,你必須通過宿主類去取它,然后,再對它進行操作,Java就是想這樣把內部類給封閉起來的,好吧,正確的寫法,我給大家貼出來:
以下是內部類的寫法:
1 public class MainClass {
2 public InnerClass getInnerClass() {
3 return new InnerClass();
4 }
5
6 public class InnerClass {
7 public String name = "name";
8
9 public String getName() {
10 return name;
11 }
12
13 public void setName(String name) {
14 this.name = name;
15 }
16 }
17 }
如果你想訪問Java內部類,你必須先拿到它的宿主類,這樣你才能對內部類進行操作:
1 public class CheckClass {
2 public static void main(String[] args) {
3 MainClass mainClass = new MainClass();
4 System.out.println(mainClass.getInnerClass().getName());
5 }
6 }
這樣的話,編譯就不會報錯了。
好了,該回答第二個問題了,就是內部類能不能訪問宿主類的私有屬性?回答是可以的。如果,你會看JVM的源碼的話,你就會看到,在編譯內部類調用主類私有變量時,會把它們轉換成一種特殊的符號,JVM會把這種符號解析成公有的,然后讓內部類調用。代碼很簡單,我就不貼了。
接著回答第三個和第四個問題:就是內部類能不能繼承別的類和接口?內部類能不能是static的?為什么不能,當然可以,這些并沒有什么約束。你自己可以試一下。
該第五個問題了:在主類的方法里面可不可以定義內部類?其實,這個問題,在我回答第一個問題的時候,已經把答案告訴了大家,就是在getInnerClass()方法里面,不就是new了一個內部類嗎。
第六個問題:初始化主類的時候是不是也把內部類給初始化了?為什么?這個嘛,如果反過來說就對了,因為如果,你想調用內部類,你就得初始化它的主類,因此,你在初始化內部類時就初始化了主類,但是,你初始化主類,如果不是顯示的去初始化,你就不可能初始化它的內部類,盡管內部類是在主類的里面。如果,你有時間,你可以到編譯的主類文件去看看。
最后一個問題就是:怎樣寫一個匿名的內部類?如果大家搞過Java Swing或者Android開發,這個問題對你來說很簡單,因為在隨便的一些事件里,你就可以定義一個匿名的內部類,然后實現它的方法。不過,為了讓更多的人明白,我把代碼貼出來,以下是我的代碼:
這是要實現的那個接口:
1 public interface SuperInterface {
2 public void print();
3 }
以下是主類的代碼:
1 public class MainClass {
2
3 public SuperInterface print(){
4
5 return new SuperInterface(){
6
7 public void print() {
8 System.out.println("Hello Anonymity Interface");
9 }};
10 }
11 }
其實上面的一段代碼就是一個匿名內部類,為什么叫匿名內部類呢?因為,你沒有給那個內部類起名字,而是直接實現那個接口,所以叫匿名內部類。
好吧,我看寫的也不少了,不過,可能我還會有疏漏的地方,希望大家能參與進來共同討論