天天看點

[改善Java代碼]使用靜态内部類提高封裝性

建議38: 使用靜态内部類提高封裝性

Java中的嵌套類(Nested Class)分為兩種:靜态内部類(也叫靜态嵌套類,Static Nested Class)和内部類(Inner Class)。内部類我們介紹過很多了,現在來看看靜态内部類。什麼是靜态内部類呢?是内部類,并且是靜态(static修飾)的即為靜态内部類。隻有在是靜态内部類的情況下才能把static修複符放在類前,其他任何時候static都是不能修飾類的。

靜态内部類的形式很好了解,但是為什麼需要靜态内部類呢?那是因為靜态内部類有兩個優點:加強了類的封裝性和提高了代碼的可讀性,我們通過一段代碼來解釋這兩個優點,如下所示:

1 public class Person {
 2     // 姓名
 3     private String name;
 4     // 家庭
 5     private Home home;
 6 
 7     public String getName() {
 8         return name;
 9     }
10 
11     public void setName(String name) {
12         this.name = name;
13     }
14 
15     public Home getHome() {
16         return home;
17     }
18 
19     public void setHome(Home home) {
20         this.home = home;
21     }
22 
23     // 構造函數設定屬性值
24     public Person(String _name) {
25         name = _name;
26     }
27 
28 
29     public static class Home {
30         public String getAddress() {
31             return address;
32         }
33 
34         public void setAddress(String address) {
35             this.address = address;
36         }
37 
38         public String getTel() {
39             return tel;
40         }
41 
42         public void setTel(String tel) {
43             this.tel = tel;
44         }
45 
46         // 家庭位址
47         private String address;
48         // 家庭電話
49         private String tel;
50 
51         public Home(String _address, String _tel) {
52             address = _address;
53             tel = _tel;
54         }
55     }
56 }      

其中,Person類中定義了一個靜态内部類Home,它表示的意思是“人的家庭資訊”,由于Home類封裝了家庭資訊,不用在Person類中再定義homeAddre、homeTel等屬性,這就使封裝性提高了。同時我們僅僅通過代碼就可以分析出Person和Home之間的強關聯關系,也就是說語義增強了,可讀性提高了。是以在使用時就會非常清楚它要表達的含義:

1 public class Client {
2     public static void main(String[] args) {  
3          //定義張三這個人  
4          Person p = new Person("張三");  
5          //設定張三的家庭資訊  
6          p.setHome(new Person.Home("上海","021"));  
7     } 
8 }      

定義張三這個人,然後通過Person.Home類設定張三的家庭資訊,這是不是就和我們真實世界的情形相同了?先登記人的主要資訊,然後登記人員的分類資訊。可能你又要問了,這和我們一般定義的類有什麼差別呢?又有什麼吸引人的地方呢?如下所示:

提高封裝性。從代碼位置上來講,靜态内部類放置在外部類内,其代碼層意義就是:靜态内部類是外部類的子行為或子屬性,兩者直接保持着一定的關系,比如在我們的例子中,看到Home類就知道它是Person的Home資訊。

提高代碼的可讀性。相關聯的代碼放在一起,可讀性當然提高了。

形似内部,神似外部。靜态内部類雖然存在于外部類内,而且編譯後的類檔案名也包含外部類(格式是:外部類+$+内部類),但是它可以脫離外部類存在,也就是說我們仍然可以通過new Home()聲明一個Home對象,隻是需要導入“Person.Home”而已。

解釋了這麼多,讀者可能會覺得外部類和靜态内部類之間是組合關系(Composition)了,這是錯誤的,外部類和靜态内部類之間有強關聯關系,這僅僅表現在“字面”上,而深層次的抽象意義則依賴于類的設計。

那靜态内部類與普通内部類有什麼差別呢?問得好,差別如下:

(1)靜态内部類不持有外部類的引用

在普通内部類中,我們可以直接通路外部類的屬性、方法,即使是private類型也可以通路,這是因為内部類持有一個外部類的引用,可以自由通路。而靜态内部類,則隻可以通路外部類的靜态方法和靜态屬性(如果是private權限也能通路,這是由其代碼位置所決定的),其他則不能通路。

(2)靜态内部類不依賴外部類

普通内部類與外部類之間是互相依賴的關系,内部類執行個體不能脫離外部類執行個體,也就是說它們會同生同死,一起聲明,一起被垃圾回收器回收。而靜态内部類是可以獨立存在的,即使外部類消亡了,靜态内部類還是可以存在的。

(3)普通内部類不能聲明static的方法和變量

普通内部類不能聲明static的方法和變量,注意這裡說的是變量,常量(也就是final static修飾的屬性)還是可以的,而靜态内部類形似外部類,沒有任何限制。

作者:SummerChill

繼續閱讀