再學Java 之 interface的成員變量


前言:最近在學多線程,寫“哲學家就餐問題(Dining Philosophers)”的時候,需要定義一個全局的變量,即哲學家的人數。常用的做法是在其中一個類中定義一個static final的變量,然后讓其他類通過類名訪問他。在這里,想使用之前實訓項目的第一版應用層協議的設計想法,即使用一個接口類來定義所有子類都會使用到的變量。然后,就引出了一個interface成員變量和static final的問題。

(一)一個簡單的問題  

  首先,看一段代碼:

 1  //Variable.java
 2  public interface Variable {
 3      public int NUM_PHILOSOPHERS = 5;
 4  }
 5   
 6  //DiningPhilosophers.java
 7  public class DiningPhilosophers implements Variable{
 8      public static void main(String[] args) {
 9          Lock[] chopsticks = new ReentrantLock[NUM_PHILOSOPHERS];
10          System.out.println(chopsticks.length);
11      }
12  }

 

  上述代碼中,DiningPhilosophers類的static方法直接使用接口中的public int變量,是否會出錯?

(二)解析

  可能會有人第一反應是不可以,因為靜態方法不能直接使用類的非靜態成員變量。我的一部分朋友也是這么想的(好吧,不排除我的誤導)

  實際上,上面的程序並沒有問題

  (1)首先,靜態方法的確不能直接使用類的非靜態成員變量。我曾經寫過一篇類似的博文《再學Java 之 解決No enclosing of type * is accessable》大家可以參考一下。

  (2)其次,所有的interface成員變量都必須是public static final 的(原因后面會解釋),所以我們在寫代碼的時候可以省略一部分修飾符,所以上面的NUM_PHILOSOPHERS就算聲明語句為 int NUM_PHILOSOPHERS=5;它依然是一個public static final變量(所以,這也解釋了,如果我們不對其賦初始值,為什么會報錯)。我們可以使用javap工具查看Variable類的編譯信息:

  

  (3)最后解釋一下為什么interface的成員變量必須是public static final的。

  我在Google上搜到了一篇比較不錯的文章《Why do we have only public static final variables in interfaces?》,下面大概翻譯一下(有改動):

  接口定義了行為的協議,而不是行為如何執行實現。實現接口的類支持該接口中定義的行為協議。

  接口中聲明的所有字段都是public static final的。為什么?

  • 如果一個變量沒有被定義為final,任何類的實現都可以改變變量的值。同時他就會變成類的實現的一部分,而接口是一個不帶任何實現的純粹的規范;
  • 如果變量是靜態的,那么這個變量就是屬於接口的,而不是屬於實例對象或者運行時的對象的。(注:由於接口不能被實例化,所以,定義為非靜態,其實也沒有意義。);
  • 接口定義了調用者如何跟接口的實現類的實例對象交互,所以如果成員不是public,那么調用者沒辦法去方法它;

  接口的每一個字段的聲明都必須是pubic static final 的,它允許我們在聲明時指定所有或者部分修飾符。同時,任何字段的聲明必須有一個初始化表達式,它可以不用一定是一個常量表達式,它的計算和賦值只會進行一次,然后這個接口字段就被初始化了(注:這是一個很有趣的特性,有興趣可以一起聊聊:-))。

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM