第 9 章 管理類別檔案

9.1 內部類別

9.1.1 成員內部類別、區域內部類別

public class OuterClass {     // 內部類別     private class InnerClass {         // ....     } }

範例 9.1 PointDemo.java

public class PointDemo {     // 內部類別     private class Point {         private int x, y;         public Point() {         }         public void setPoint(int x, int y) {             this.x = x;             this.y = y;         }         public int getX() { return x; }         public int getY() { return y; }     }     private Point[] points;     public PointDemo(int length) {         points = new Point[length];         for(int i = 0; i < points.length; i++) {             points[i] = new Point();             points[i].setPoint(i*5, i*5);         }     }     public void showPoints() {         for(int i = 0; i < points.length; i++) {             System.out.printf("Point[%d]: x = %d, y = %d%n",                      i, points[i].getX(), points[i].getY());        }     } }

範例 9.2 PointShow.java

public class PointShow {     public static void main(String[] args) {         PointDemo demo = new PointDemo(5);         demo.showPoints();     } }

Point[0]: x = 0, y = 0Point[1]: x = 5, y = 5Point[2]: x = 10, y = 10Point[3]: x = 15, y = 15Point[4]: x = 20, y = 20

public class Outer {    public static class Inner {        ....    }    ....}

Outer.Inner inner = new Outer.Inner();

9.1.2 匿名內部類別

new [類別或介面()] { // 實作 }

範例 9.3 AnonymousClassDemo.java

public class AnonymousClassDemo {     public static void main(String[] args) {         Object obj =             new Object() {                 public String toString() { // 重新定義toString()                    return "匿名類別物件";                 }             };         System.out.println(obj);     } }

匿名類別物件

....    public void someMethod() {        int x = 10; // 沒有宣告final        Object obj =             new Object() {                 public String toString() {                    return String.valueOf(x); // x不可在匿名類別中使用                }             };         System.out.println(obj);     }....

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

....    public void someMethod() {        final int x = 10; // 宣告final        Object obj =             new Object() {                 public String toString() {                    return String.valueOf(x); // x可在匿名類別中使用                }             };         System.out.println(obj);     }....

9.2 package 與 import

9.2.1 設定套件（package）

Java 提供「套件」（package）來管理類別，套件被設計與檔案系統結構相對應，如果您的套件設定為onlyfun.caterpillar，則該類別應該在 Classpath 可以存取到的路徑下的 onlyfun 目錄下之 caterpillar 目錄找到，沒有設定套件管理的類別會歸為「預設套件」（default package）。

範例 9.4 PackageDemo.java

package onlyfun.caterpillar;public class PackageDemo {     public static void main(String[] args) {         System.out.println("Hello! World!");     } }

javac -d . PackageDemo.java 

java onlyfun.caterpillar.PackageDemo

範例 9.5 Point2D.java

package onlyfun.caterpillar; public class Point2D {     private int x;    private int y;    public Point2D() {    }     public Point2D(int x, int y) {        this.x = x;         this.y = y;    }     public int getX() { return x; }     public int getY() { return y; } }

javac -d . Point2D.java

範例 9.6 Point2DDemo.java

public class Point2DDemo {     public static void main(String[] args) {         onlyfun.caterpillar.Point2D p1 = new             onlyfun.caterpillar.Point2D(10, 20);        System.out.printf("p1: (x, y) = (%d, %d)%n",            p1.getX(), p1.getY());     } }

p1: (x, y) = (10, 20)

bad class file: .\Point2D.classclass file contains wrong class: onlyfun.caterpillar.Point2DPlease remove or make sure it appears in the correct subdirectory of the classpath.        Point2D p1 = new Point2D(10, 20);        ^1 error

9.2.2 import 的意義

範例 9.7 Point2DDemo2.java

import onlyfun.caterpillar.Point2D;public class Point2DDemo2 {     public static void main(String[] args) {         Point2D p1 = new Point2D(10, 20);        System.out.printf("p1: (x, y) = (%d, %d)%n",            p1.getX(), p1.getY());     } }

範例 9.8 Point2DDemo3.java

import onlyfun.caterpillar.*;public class Point2DDemo3 {     public static void main(String[] args) {         Point2D p1 = new Point2D(10, 20);        System.out.printf("p1: (x, y) = (%d, %d)%n",            p1.getX(), p1.getY());     } }

bad class file: .\Point2D.javafile does not contain class Point2DPlease remove or make sure it appears in the correct subdirectory of the classpath.

javac -d ./classes ./src/*.java

java Point2DDemo3

java -cp ./classes Point2DDemo3

import java.util.Arrays;import onlyfun.caterpillar.Arrays;public class SomeClass {    ....}

java.util.Arrays is already defined in a single-type importimport onlyfun.caterpillar.Arrays;^1 error

Java SE 平台的 .class 檔案是儲存在 JRE 安裝目錄的 /lib 下的 rt.jar 中，而額外的第三方（Third- party）元件可以放 /lib/ext 中，以及您自己設定的 Classpath。

9.2.3 public 與套件

Point2DDemo.java:3: onlyfun.caterpillar.Point2D is not public in onlyfun.caterpillar;     cannot be accessed from outside package        onlyfun.caterpillar.Point2D p1 = new

Point2DDemo.java:7: getX() is not public in onlyfun.caterpillar.Point2D; cannot be     accessed from outside package           p1.getX(), p1.getY());              ^

package onlyfun.caterpillar;class SomeClass {    // ...    public void someMethod() {        // ....    }}

package onlyfun.caterpillar;class SomeClass {    // ...    void someMethod() {        // ....    }}

package onlyfun.caterpillar;public class Test {    ....}

package onlyfun.caterpillar;public class Test {    public Test() {    }    ....}

package onlyfun.caterpillar;public class Test {    public Test(int i) {        ...    }    ....}

Test test = new Test();

package onlyfun.caterpillar;public class Test {    public Test() { // 即使沒用到，也先建立一個空的建構方法    }    public Test(int i) {        ...    }    ....}

package onlyfun.caterpillar;public class Test {}

package onlyfun.caterpillar;class Test {}

package onlyfun.caterpillar;class Test {    Test() {    }}

表 9.1 權限設定為套件的關係

private OK
(default) OK OK
protected OK OK OK
public OK OK OK OK

9.2.4 import 靜態成員

範例 9.9 HelloWorld.java

import static java.lang.System.out;public class HelloWorld {    public static void main(String[] args) {        out.println("Hello! World!");    }}

範例 9.10 ImportStaticDemo.java

import static java.lang.System.out;import static java.util.Arrays.sort;public class ImportStaticDemo {    public static void main(String[] args) {        int[] array = {2, 5, 3, 1, 7, 6, 8};        sort(array);        for(int i : array) {            out.print(i + " ");        }    }}

1 2 3 5 6 7 8

import static java.util.Arrays.*;

“import static” 語法可以讓您少打一些字，但是您要注意名稱衝突問題，對於名稱衝突編譯器可能透過以下的幾個方法來解決：

• 成員覆蓋

如果類別中有同名的資料成員或方法，則優先選用它們。

• 區域變數覆蓋

嘗試使用重載機制判斷，也就是透過方法名稱及參數列的比對來選擇適當的方法。

package onlyfun.caterpillar;public class Arrays {    public static void sort(int[] arr) {        // ....    }}

import static java.lang.System.out;import static java.util.Arrays.sort;import static onlyfun.caterpillar.Arrays.sort;public class ImportStaticDemo2 {    public static void main(String[] args) {        int[] array = {2, 5, 3, 1, 7, 6, 8};        sort(array);        for(int i : array) {            out.print(i + " ");        }    }}

ImportStaticDemo2.java:9: reference to sort is ambiguous, both method sort(int[]) in     onlyfun.caterpillar.Arrays and method sort(int[]) in java.util.Arrays match     sort(array);        ^1 error

9.3 接下來的主題

• 會定義成員內部類別
• 會使用匿名內部類別
• 知道內部類別編譯過後的 .class 檔名稱命名方式
• 會使用套件整理類別並瞭解其與實體目錄之關係
• 知道”public”與套件的權限關係
• 瞭解”import”、”import static” 的真正目的