「導入」關鍵字實際上並沒有導入什麼。基本上它只是一種通過類名引用類的完整路徑的方法。所以當我們說
import java.lang.String;
然後我們可以在我們的代碼中通過它的名字「String」來引用那個類。在編譯時,任何我們擁有類「String」的地方都會被替換爲「java.lang.String」。而已。
這也是爲什麼,如果你有一個以上的類具有相同的名稱,但在不同的包,你可以輸入最多隻是其中之一。其他課程必須以其全名。
走上問題:
1.確實的A.class存儲有關其自身內部乙的一些信息?只是名稱,被調用的方法,使用的最終變量?如果編譯後的A.class中沒有太多有關B的信息 - 爲什麼我們不能編譯沒有B.class的A?
不是真的。當您調用其他類時,類A將只使用完全限定的類名稱和方法簽名。使用我們的字符串例如,調用
mystring.charAt(0)
將編譯成字節碼是這樣看的東西:
aload_1 [myString]
iconst_0
invokevirtual java.lang.String.charAt(int)
其他類的任何內部狀態被存儲在我們的A類裏面除了內聯可能常量。因此,如果價值可能在未來發生變化,請務必在字段public final
上注意。 (參見下面的解決方法)
當我們編譯A類時,我們需要B.class
,因此編譯器可以確保類B具有我們要使用的那些方法。
2.如果我們在與B.class包這是另外一個人更換B.class - 當它工作,何時不? 新B.class會工作,如果完全限定域名(包裝等)是相同的,它具有我們正在嘗試使用正確的方法簽名。新的B類可以添加新的方法,甚至可以使用不同的方法實現。但是,它不能修改我們使用的方法的方法簽名。如果舊方法不再存在或者其簽名不同,我們將在編譯時得到一個java.lang.LinkageError
。
3.如果A.class與新的B.class運行正常,那麼A.class可以使用來自OLD B.class的一些信息,它在編譯過程中併入A.class中?即我們最終是否可以在我們的項目中使用B.class的混合邏輯?從老B.這
唯一的問題可能是內聯常量就是爲什麼Java Coding Guidelines項目31項(第115頁)說:「不要使用公共決賽,其值在以後的版本可能恰克常量」。 相反,做一個getter方法: 例如:
class BadFoo{
//bad, VERSION could be inlined
//and later when we change the version, other classes will have the old value!
public static final int VERSION =1;
}
class BetterFoo{
private static int version =1;
//outside classes must call method getVersion()
//field version can not be inlined at compile time.
//JIT may inline at runtime which is OK
public static final int getVersion(){
return version;
}
}
4.關於上述問題的答案築底:我們能以某種方式編譯類依賴於其他類的不知道他們在編譯時確切的實現,並提供依賴只在運行時?
是,代碼接口。
接口應該包含所有你需要調用的方法。我們的A類應該只能通過接口引用調用者。如果我們要調用的對象實例被傳入,那麼類A不知道(或者需要知道)實際類型是什麼,並且在編譯時不需要知道它。
這是主要目的和Dependency Injection
優勢之一甚至除了依賴注入,編碼到接口方面具有優勢。例如,如果我們使用Map
而不是HashMap
,稍後我們可以通過更改代碼中的一個位置來更改代碼以使用不同的Map實現,例如ConcurrentHashMap
。我們其餘的代碼將會工作,因爲它只知道它是一個Map。
是不是「編程接口」是關於什麼? – 2014-10-16 19:36:10