術語Override,Overload,Hide,Shadow,Obscure的解釋

Override,即重寫,Java最基礎的編程技巧之一。僅針對實例方法,並且能夠被子類所訪問, 且子類該方法的訪問權限至少大於父類。遵循運行期綁定原則。

Overload,即重載,Java最基礎的編程技巧之一。要求方法名相同,簽名不同(參數類型,參數個數,返回類型等)。遵循編譯期綁定原則。

Hide,即隱藏,指實例域,靜態方法,成員類型可以分別隱藏繼承自超類的可訪問的相同名字的實例域,靜態方法,成員類型。

Shadow,即遮蔽,指一個變量,方法或類型可以分別遮蔽一個閉合的文本範圍內的具有相同名字的所有變量,方法或類型。

Obscure,即遮掩,指一個變量可以遮掩一個相同名字的類型,只要它們在同一個範圍內。

重點分析Hide,Shadow,Obscure的區別。

一、Hide存在於子類繼承自父類的場景,且子類和父類具有相同名字的實例域,靜態方法,成員類型。並且能夠隱藏的東西都是父類可以訪問到的。且對於靜態方法來說,隱藏要求子類該靜態方法的訪問權限大於等於父類訪問權限。

例如:

class Foo {
     public String className = "foo";
     public static void f() {}
     public static class innerClass {
          static String innerName = "FooInner";
     }
}

class Sub extends Foo {
     String className = "sub";
     static void f() {}
     static class innerClass {
          static String innerName = "SubInner";
     }
}

這個案例就是隱藏,但是Sub的f()無法編譯通過,因爲它的訪問權限小於父類。但是實例域或成員類型(Member Type)對於訪問權限沒有這個限制。

關於成員類型,Oracle官方給瞭解析,鏈接: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.5。可以看出成員類型大概指內部類或者接口。

二、Shadow存在於一個閉合的範圍內,當一個變量與另一個實例域或者對象或者方法同名將發生遮蔽,最常見的兩種遮蔽:

1.成員變量名和局部變量名相同,這局部變量所在的範圍內,無法訪問到成員變量。

2.構造方法的參數名和成員變量名相同,成員變量被遮蔽,這種遮蔽是合法的,也是類初始化有參構造器最常見的寫法。

例如:

public 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
          
          Belt belt = new Belt(3);
          System.out.println(belt.getSize());
     }
}

class Belt {
     private int size;
     public Belt(int size) { // Parameter shadows Belt.size
          this.size = size;
     }
     public int getSize() {
          return size;
     }
     public void setSize(int size) {
          this.size = size;
     }
}

三、Obscure存在於同一個範圍內,一個變量名遮掩另一個相同變量名的類型。

例如:

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!");
     }
}

這個例子中System作爲一個不規範的變量名遮掩了java.lang.System類,導致了Obscure類中,所有的本該引用java.lang.System的地方都引用了String類型的System,從而導致編譯錯誤。

比較Shadow和Obscure,二者很相似。但是還是有點區別:

1.由Shadow導致的遮蔽通常不會發生編譯錯誤。它只是在一個閉合的文本範圍內覆蓋了另一個同名的實例。但是由Obscure導致的遮掩卻極易導致編譯錯誤,尤其是和Java平臺已有的類重名時。

2.遮蔽通常只是覆蓋一個實例或方法,而遮掩卻覆蓋了整個類型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章