名稱重用有時會導(dǎo)致編譯錯誤,但有時卻不會,導(dǎo)致發(fā)生難以發(fā)現(xiàn)的問題,所以一定要注意。
下面將所有的名稱重用情況列出,并附帶例子,在日常的開發(fā)中一定還會遇到類似的問題,希望能有所幫助。
這部分涉及到的靜態(tài)綁定和動態(tài)綁定問題,理解后對于泛型能有更好的理解,相關(guān)筆記請看文末。
-
重寫(Overriding)
子類可以重寫其父類中可訪問到的具有相同簽名的所有成員方法[JLS 8.4.8.1]。
JVM將會根據(jù)實例的運(yùn)行期類型(對象)來選擇要調(diào)用的重寫方法[JLS 15.12.4.4]。
靜態(tài)方法是無法重寫的,因為重寫的要求是要動態(tài)綁定(對象),而靜態(tài)方法是靜態(tài)綁定(類)。final方法也是無法重寫的,因為使用final的目的就是防止其被重寫。注意,這里說的搜是方法。
在 JDK 1.5 及以上中使用 @Override 注解,防止將需要重寫的方法錯寫為重載。class Base { public void f() {} } class Derived extends Base { @Override public void f() {} // overrrides Base.f() } -
重載(Overloading)
在一個類中,可以以相同的名稱和不同的簽名來構(gòu)成重載,重載方法的調(diào)用是在編譯階段選定的(類)。
簽名指的是方法名及參數(shù)列表,返回類型不是簽名的一部分,所以返回類型不同但是簽名相同的重載是無法編譯通過的。
盡量要確保重載的方法在相同的簽名上有相同的行為。class CircuitBreaker { public void f(int i) { } // int overloading public void f(String s) { } // String overloading } -
隱藏(Hiding)
一個成員變量、靜態(tài)方法或成員類型可分別隱藏其父類中可訪問到的具有相同名稱(方法而言是方法簽名)的所有成員變量、靜態(tài)方法或成員類型,隱藏的成員不會被繼承。
不要去重用 java.lang 包下的類型名。
補(bǔ)充一下,內(nèi)部成員類的參數(shù)類型(泛型)可以隱藏外部類的參數(shù)類型(這個問題在IDEA中已經(jīng)有溫馨提示)。class Base { public static String fStr = "base"; public static void f() {System.out.println(fStr); } static class BaseType { public static String type = "base"; } } class Derived extends Base { private static String fStr = "derived"; //hides Base.fStr, even can change the access! public static void f() { System.out.println(fStr); } // hides Base.f() //hides Base.BaseType static class BaseType { public static String type = "derived"; } } -
遮蔽(Shadowing)
一個變量、方法或類型可以分別遮蔽在類中具有相同名稱的所有成員變量、成員方法或成員類型。如果一個實體被遮蔽了,根據(jù)實體的不同,有時候根本無法引用到。[JLS 6.3.1]class WhoKnows { static String sentence = "I don’t know."; public static void main(String[] args) { String sentence = "I know!"; // shadows static field System.out.println(sentence); // prints local variable } } //最常見的遮蔽,不是沒有風(fēng)險,但為慣用法。 class Belt { private final int size; public Belt(int size) { // Parameter shadows Belt.size this.size = size; } } -
遮掩(Obscuring)
一個變量名可以遮掩具有相同名稱的一個類型(類),只要他們屬于同一個作用域。類似的,一個變量或一個引用可以遮掩一個包。遮掩是惟一一種兩個名稱位于不同的名稱空間的名稱重用形式,包括:變量、方法、包或類型。
按照命名規(guī)范來進(jìn)行命名可以有效防止遮掩的發(fā)生。public class Obscure { static String System; // Obscures type java.lang.System public static void main(String[] args) { // Next line won’t compile: System refers to static field System.out.println("hello, obscure world!"); } }