JAVA面試題解惑系列(三)——變量(屬性)的覆蓋
http://www.javaeye.com/topic/211281變量,或者叫做類的屬性,在繼承的情況下,如果父類和子類存在同名的變量會出現什么情況呢?這一次,我們就一起來回顧一下這個問題——變量(屬性)的覆蓋。
這個問題雖然簡單,但是情況卻比較復雜。因為我們不僅要考慮變量、靜態變量和常量三種情況,還要考慮private、friendly(即不加訪問修飾符)、protected和public四種訪問權限下對屬性的不同影響。
我們先從普通變量說起。依照我們的慣例,先來看一段代碼:
1
class ParentClass {
2
private String privateField = "父類變量--private";
3
4
/* friendly */String friendlyField = "父類變量--friendly";
5
6
protected String protectedField = "父類變量--protected";
7
8
public String publicField = "父類變量--public";
9
10
// private的變量無法直接訪問,因此我們給他增加了一個訪問方法
11
public String getPrivateFieldValue() {
12
return privateField;
13
}
14
}
15
16
public class SubClass extends ParentClass {
17
private String privateField = "子類變量--private";
18
19
/* friendly */String friendlyField = "子類變量--friendly";
20
21
protected String protectedField = "子類變量--protected";
22
23
public String publicField = "子類變量--public";
24
25
// private的變量無法直接訪問,因此我們給他增加了一個訪問方法
26
public String getPrivateFieldValue() {
27
return privateField;
28
}
29
30
public static void main(String[] args) {
31
// 為了便于查閱,我們統一按照private、friendly、protected、public的順序
32
// 輸出下列三種情況中變量的值
33
34
// ParentClass類型,ParentClass對象
35
ParentClass parentClass = new ParentClass();
36
System.out.println("ParentClass parentClass = new ParentClass();");
37
System.out.println(parentClass.getPrivateFieldValue());
38
System.out.println(parentClass.friendlyField);
39
System.out.println(parentClass.protectedField);
40
System.out.println(parentClass.publicField);
41
42
System.out.println();
43
44
// ParentClass類型,SubClass對象
45
ParentClass subClass = new SubClass();
46
System.out.println("ParentClass subClass = new SubClass();");
47
System.out.println(subClass.getPrivateFieldValue());
48
System.out.println(subClass.friendlyField);
49
System.out.println(subClass.protectedField);
50
System.out.println(subClass.publicField);
51
52
System.out.println();
53
54
// SubClass類型,SubClass對象
55
SubClass subClazz = new SubClass();
56
System.out.println("SubClass subClazz = new SubClass();");
57
System.out.println(subClazz.getPrivateFieldValue());
58
System.out.println(subClazz.friendlyField);
59
System.out.println(subClazz.protectedField);
60
System.out.println(subClazz.publicField);
61
}
62
}
63

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

這段代碼的運行結果如下:
- ParentClass parentClass = new ParentClass();
- 父類變量--private
- 父類變量--friendly
- 父類變量--protected
- 父類變量--public
- ParentClass subClass = new SubClass();
- 子類變量--private
- 父類變量--friendly
- 父類變量--protected
- 父類變量--public
- SubClass subClazz = new SubClass();
- 子類變量--private
- 子類變量--friendly
- 子類變量--protected
- 子類變量--public
從上面的結果中可以看出,private的變量與其它三種訪問權限變量的不同,這是由于方法的重寫(override)而引起的。關于重寫知識的回顧留給以后的章節,這里我們來看一下其它三種訪問權限下變量的覆蓋情況。
分析上面的輸出結果就會發現,變量的值取決于我們定義的變量的類型,而不是創建的對象的類型。
在上面的例子中,同名的變量訪問權限也是相同的,那么對于名稱相同但是訪問權限不同的變量,情況又會怎樣呢?事實勝于雄辯,我們繼續來做測試。由于private變量的特殊性,在接下來的實驗中我們都把它排除在外,不予考慮。
由于上面的例子已經說明了,當變量類型是父類(ParentClass)時,不管我們創建的對象是父類(ParentClass)的還是子類(SubClass)的,都不存在屬性覆蓋的問題,因此接下來我們也只考慮變量類型和創建對象都是子類(SubClass)的情況













運行結果:
子類變量













上面兩段不同的代碼,輸出結果確是相同的。事實上,我們可以將父類和子類屬性前的訪問修飾符在friendly、protected和public之間任意切換,得到的結果都是相同的。也就是說訪問修飾符并不影響屬性的覆蓋,關于這一點大家可以自行編寫測試代碼驗證。
對于靜態變量和常量又會怎樣呢?我們繼續來看























- 子類靜態變量
- 子類常量
- 子類靜態常量
雖然上面的結果中包含“子類靜態變量”和“子類靜態常量”,但這并不表示父類的“靜態變量”和“靜態常量”可以被子類覆蓋,因為它們都是屬于類,而不屬于對象。
上面的例子中,我們一直用對象來對變量(屬性)的覆蓋做測試,如果是基本類型的變量,結果是否會相同呢?答案是肯定的,這里我們就不再一一舉例說明了。
最后,我們來做個總結。通過以上測試,可以得出一下結論:
- 由于private變量受訪問權限的限制,它不能被覆蓋。
- 屬性的值取父類還是子類并不取決于我們創建對象的類型,而是取決于我們定義的變量的類型。
- friendly、protected和public修飾符并不影響屬性的覆蓋。
- 靜態變量和靜態常量屬于類,不屬于對象,因此它們不能被覆蓋。
- 常量可以被覆蓋。
- 對于基本類型和對象,它們適用同樣的覆蓋規律。
posted on 2008-08-22 13:07 gdufo 閱讀(241) 評論(0) 編輯 收藏 所屬分類: JAVA 基礎