java中覆蓋和隱藏的問題

近期復(fù)習(xí)java時,發(fā)覺了自己很多沒掌握的知識點,現(xiàn)在每天總結(jié)一點點,一點點的積累,一點點的進步。

今天的解決問題——java中覆蓋和隱藏的問題(方法和變量)

參考網(wǎng)址:http://school.cnd8.com/java/jiaocheng/10836.htm

          http://heisetoufa.javaeye.com/blog/227345

 

1.先來總結(jié)java中方法的覆蓋和隱藏

一個大的原則:靜態(tài)方法不能被覆蓋。實例方法被覆蓋,靜態(tài)方法被隱藏。被覆蓋的方法只有覆蓋它們的類才能訪問它們,而訪問被隱藏的方法是提供該方法的全局名。

例子:

01: class Super
02: {
03: static String greeting()
04: {
05: return "Goodnight";
06: }
07:
08: String name()
09: {
10: return "Richard";
11: }
12: }
  
01: class Sub extends Super
02: {
03: static String greeting()
04: {
05: return "Hello";
06: }
07:
08: String name()
09: {
10: return "Dick";
11: }
12: }
  
01: class Test
02: {
03: public static void main(String[] args)
04: {
05: Super s = new Sub();
06: System.out.println(s.greeting() + ", " + s.name());
07: }
08: }
程序運行結(jié)果:Goodnight,Dick
分析:在main函數(shù)中,創(chuàng)建了一個子類sub對象實例,通過賦值號我們可以看成其被強制轉(zhuǎn)換成父類super類型。由于greeting是靜態(tài)方法,它僅僅是被子類sub隱藏,所以通過強制轉(zhuǎn)換成父類super的對象實例s調(diào)用時,實際上調(diào)用的是父類的greeting方法;而name方法為實例方法,其被子類sub覆蓋,所以s.name()是調(diào)用的子類name方法。
在繼承時需要注意的幾點原則:
1)試圖用子類的靜態(tài)方法隱藏父類中同樣標識的實例方法不合法,編譯器會報錯;
2)試圖用子類的實例方法覆蓋父類中同樣標識的靜態(tài)方法也不合法,編譯器會報錯;
3)靜態(tài)方法和最終方法不能被覆蓋;
4)實例方法能夠被覆蓋;
5)抽象方法必須在具體類中被覆蓋。
2.再來總結(jié)下變量的覆蓋和隱藏
原網(wǎng)址的變量分的很詳細,不仔細看還被繞的有點糊涂。總結(jié)了下,不管是靜態(tài)變量還是非靜態(tài)變量,只要是成員變量,它們被覆蓋和被隱藏的原則一樣。原則:成員變量能夠被子類同名的成員變量隱藏,而局部變量和形參不會被隱藏。
例子:
class Base {
 int x = 1;
 static int y=2;
 int z=3;
 int method() {
 return x;
 }
}
  
class Subclass extends Base {
 int x = 4;
 int y=5;
 static int z=6;
 int method() {
 return x;
 }
}
  
public class Test {
 public static void main(String[] args) {
 Subclass s=new Subclass();
 System.out.println(s.x + " " + s.y +" "+ s.z);
 System.out.println(s.method());
 
 Base b = (Subclass)s;
 System.out.println(b.x + " " + b.y +" "+ b.z);
 System.out.println(b.method());
 }
}
結(jié)果:4 5 6 
   4
   1 2 3
   4
分析:在main方法中,開始創(chuàng)建了一個subclass對象實例,對于第一個輸出很好理解;后將對象實例s強制轉(zhuǎn)換成父類Base類型,由于父類的成員變量只是被隱藏,所以通過強制轉(zhuǎn)換成父類類型的對象實例調(diào)用時,調(diào)用的是父類中的變量,而method方法是被子類同名方法所覆蓋,所以調(diào)用時依然調(diào)用的子類method方法。
 
3.最后變量和方法的隱藏及其覆蓋的不同
一個類的實例無法通過使用全局名或者強制自己轉(zhuǎn)換成父類型,來訪問父類中被隱藏的方法,但是可以通過強制轉(zhuǎn)換為父類型之后,訪問父類型中被隱藏的變量。靜態(tài)方法不能覆蓋父類的實例方法,而靜態(tài)變量卻可以隱藏父類的一個同名實例變量。實例方法不能覆蓋父類的同名靜態(tài)方法,而變量卻可以隱藏父類的同名成員變量。
 
4.我最終發(fā)現(xiàn)和解決的問題
public class ClassA{
public void methodOne(int i){}
public void methodTwo(int i){}
public static void methodThree(int i){}
public static void methodFour(int i){}
}
 
public class ClassB{
public static void methodOne(int i){}
public void methodTwo(int i){}
public void methodThree(int i){}
public static void methodFour(int i){}
}
a.哪些方法覆蓋了超類中的方法? methodTwo
b.哪些方法隱藏了超類中的方法? methodFour
其他兩個方法編譯會報錯,因為不能用子類的靜態(tài)方法隱藏父類中同名的實例方法,不能用子類的實例方法覆蓋父類中同名的靜態(tài)方法。