Skip to content

Commit 25b01a2

Browse files
committed
Update CH09.md
1 parent a220f58 commit 25b01a2

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

docs/CH09.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616

1717
先來介紹成員內部類別,基本上是在一個類別中直接宣告另一個類別,例如:
1818

19+
```java
1920
public class OuterClass {
2021
// 內部類別
2122
private class InnerClass {
2223
// ....
2324
}
2425
}
26+
```
2527

2628
成員內部類別同樣也可以使用 "public"、"protected" 或 "private" 來修飾其存取權限,範例 9.1 簡單示範成員內部類別的使用。
2729

@@ -91,12 +93,14 @@ public class PointShow {
9193

9294
內部類別還可以被宣告為 "static",不過由於是 "static",它不能存取外部類別的方法,而必須透過外部類別所生成的物件來進行呼叫,被宣告為 static的內部類別,事實上也可以看作是另一種名稱空間的管理方式,例如:
9395

96+
```java
9497
public class Outer {
9598
public static class Inner {
9699
....
97100
}
98101
....
99102
}
103+
```
100104

101105
您可以如以下的方式來使用 Inner 類別:
102106

@@ -110,9 +114,11 @@ public class PointShow {
110114

111115
內部匿名類別可以不宣告類別名稱,而使用 "new" 直接產生一個物件,內部匿名類別可以是繼承某個類別或是實作某個介面,內部匿名類別的宣告方式如下:
112116

117+
```java
113118
new [類別或介面()] {
114119
// 實作
115120
}
121+
```
116122

117123
一個使用內部匿名類別的例子如範例7.3所示,您直接繼承 Object 類別定義一個匿名類別,重新定義 toString() 方法,並使用匿名類別直接產生一個物件。
118124

@@ -138,6 +144,7 @@ public class AnonymousClassDemo {
138144

139145
注意如果要在內部匿名類別中使用外部的區域變數,變數在宣告時必須為 "final",例如下面的陳述是無法通過編譯的:
140146

147+
```java
141148
....
142149
public void someMethod() {
143150
int x = 10; // 沒有宣告final
@@ -150,13 +157,15 @@ public class AnonymousClassDemo {
150157
System.out.println(obj);
151158
}
152159
....
160+
```
153161

154162
在進行編譯時,編譯器會回報以下的錯誤:
155163

156164
local variable x is accessed from within inner class; needs to be declared final
157165

158166
您要在宣告區域變數x時加上"final"才可以通過編譯:
159167

168+
```java
160169
....
161170
public void someMethod() {
162171
final int x = 10; // 宣告final
@@ -169,6 +178,7 @@ public class AnonymousClassDemo {
169178
System.out.println(obj);
170179
}
171180
....
181+
```
172182

173183
為什麼要加上 "final" 宣告呢?原因在於區域變數 x 並不是真正被拿來於內部匿名類別中使用,x 會被匿名類別複製作為資料成員來使用,由於真正在匿名類別中的x是複製品,即使您在內部匿名類別中對 x 作了修改(例如 x=10 的指定),也不會影響真正的區域變數x,事實上您也通不過編譯器的檢查,因為編譯器會要求您加上 "final" 關鍵字,這樣您就知道不能在內部匿名類別中改變 x 的值,因為即使能改變也沒有意義。
174184

@@ -359,56 +369,69 @@ public class Point2DDemo3 {
359369

360370
類別上的權限設定會約束類別成員上的權限設定,所以如果類別上不宣告 "public",而類別成員上設定了 "public",則類別成員同樣的也只能被同一個套件的類別存取,也就是說如果您這麼撰寫程式:
361371

372+
```java
362373
package onlyfun.caterpillar;
363374
class SomeClass {
364375
// ...
365376
public void someMethod() {
366377
// ....
367378
}
368379
}
380+
```
369381

370382
其效果等同於:
371383

384+
```java
372385
package onlyfun.caterpillar;
373386
class SomeClass {
374387
// ...
375388
void someMethod() {
376389
// ....
377390
}
378391
}
392+
```
379393

380394
由這邊的討論,可以再來看看預設建構方法的權限。首先要知道的是,當您在 Java 中定義一個類別,但沒有定義建構方法時,編譯器會自動幫您產生一個預設建構方法,也就是說,如果您這麼寫:
381395

396+
```java
382397
package onlyfun.caterpillar;
383398
public class Test {
384399
....
385400
}
401+
```
386402

387403
則編譯器會自動加上預設建構方法,也就是相當於這麼寫:
388404

405+
```java
389406
package onlyfun.caterpillar;
390407
public class Test {
391408
public Test() {
392409
}
393410
....
394411
}
412+
```
395413

396414
如果您自行定義建構方法,則編譯器就不會幫您加上預設建構方法,所以當您這麼定義時:
397415

416+
```java
398417
package onlyfun.caterpillar;
399418
public class Test {
400419
public Test(int i) {
401420
...
402421
}
403422
....
404423
}
424+
```
405425

406426
則在建構時,就必須指明使用哪個建構方法,簡單的說,您就不能使用以下的方式來建構:
407427

428+
```java
408429
Test test = new Test();
430+
```
409431

410432
有時會建議即使沒有用到,在定義自己的建構方法的同時,也加上個沒有參數的建構方法,例如:
411433

434+
```java
412435
package onlyfun.caterpillar;
413436
public class Test {
414437
public Test() { // 即使沒用到,也先建立一個空的建構方法
@@ -419,28 +442,35 @@ public class Point2DDemo3 {
419442
}
420443
....
421444
}
445+
```
422446

423447
要注意的是,在繼承時,如果您沒有使用 super() 指定要使用父類別的哪個建構方法,則預設會尋找父類別中無參數的建構方法。
424448

425449
預設建構方法的存取權限是跟隨著類別的存取權限而設定,例如:
426450

451+
```java
427452
package onlyfun.caterpillar;
428453
public class Test {
429454
}
455+
```
430456

431457
由於類別宣告為 public,所以預設建構方法存取權限為 public。如果是以下的話:
432458

459+
```java
433460
package onlyfun.caterpillar;
434461
class Test {
435462
}
463+
```
436464

437465
則預設建構方法存取權限為套件存取權限,也就是編譯器會自動為您擴展為:
438466

467+
```java
439468
package onlyfun.caterpillar;
440469
class Test {
441470
Test() {
442471
}
443472
}
473+
```
444474

445475
在這邊整理一下 private、protected、public 與 default 與類別及套件的存取關係:
446476

@@ -515,15 +545,18 @@ public class ImportStaticDemo {
515545

516546
如果編譯器無法判斷,則會回報錯誤,例如若您定義了如下的類別:
517547

548+
```java
518549
package onlyfun.caterpillar;
519550
public class Arrays {
520551
public static void sort(int[] arr) {
521552
// ....
522553
}
523554
}
555+
```
524556

525557
然後如下撰寫程式:
526558

559+
```java
527560
import static java.lang.System.out;
528561
import static java.util.Arrays.sort;
529562
import static onlyfun.caterpillar.Arrays.sort;
@@ -536,6 +569,7 @@ public class ImportStaticDemo {
536569
}
537570
}
538571
}
572+
```
539573

540574
由於從 java.util.Arrays.sort 與 onlyfun.caterpillar.Arrays.sort 的兩行 "import static" 上都可以找到 sort,編譯器無法辦別要使用哪一個 sort() 方法,因而編譯時會出現以下的錯誤:
541575

0 commit comments

Comments
 (0)