第9章
?管理類別檔案
–內部類別
–package與import
成員內部類別、區域內部類別?成員內部類別,基本上是在一個類別中直
接宣告另一個類別
public class OuterClass{
// 內部類別
private class InnerClass{
// ....
}
}
?所產生的檔案名稱為「外部類別名稱$內部類別名稱.class」
成員內部類別、區域內部類別?區域內部類別定義於一個方法中,類別的可視範圍與生成之物件僅止於該方法之中?內部類別還可以被宣告為"static“
?由於是“static”,它不能存取外部類別的方法,而必須透過外部類別所生成的物件來進行呼叫
成員內部類別、區域內部類別?被宣告為static的內部類別,事實上也可以看作是另一種名稱空間的管理方式
public class Outer {
public static class Inner {
....
}
....
}
Outer.Inner inner = new Outer.Inner();
匿名內部類別
?內部匿名類別可以是繼承某個類別或是實作某個介面
new [類別或介面()] {
// 實作
}
Object obj=
new Object() {
public String toString() { // 重新定義toString()
return "匿名類別物件";
}
};
System.out.println(obj);
匿名內部類別
?注意如果要在內部匿名類別中使用外部的
區域變數,變數在宣告時必須為"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);
}
....
匿名內部類別
?區域變數x並不是真正被拿來於內部匿名類別中使用
?x會被匿名類別複製作為資料成員來使用?編譯器會要求您加上“final”關鍵字,這樣您就知道不能在內部匿名類別中改變x的值?內部匿名類別在編譯完成之後會產生「外部類別名稱$編號.class」,編號為1、2、3...n,每個編號n的檔案對應於第n個匿名類別
設定套件(package)
?套件被設計與檔案系統結構相對應
?為了要能建立與套件相對應的檔案系統結構,您在編譯時可以加入"-d"參數,並指定產生的類別檔案要儲存在哪一個目錄之下package onlyfun.caterpillar;
public class PackageDemo{
public static void main(String[] args) {
System.out.println("Hello! World!");
}
}
設定套件(package)
?javac-d . UsePackage.java
?在目前的工作位置中會出現onlyfun目錄,之下會有個caterpillar目錄,而當中有個PackageDemo.class檔案?“package”的設定會成為類別名稱的一部份–完整類別名onlyfun.caterpillar.PackageDemo –java onlyfun.caterpillar.PackageDemo
設定套件(package)?「完全描述」(Fully qualified)名稱–完整的指出「套件加類別」名稱
onlyfun.caterpillar.Point2D p1 = new
onlyfun.caterpillar.Point2D(10, 20);
?最後編譯完成的.class檔案必須放在onlyfun 目錄的caterpillar目錄下
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
import的意義
?您可以使用"import"關鍵字,告知編譯器您所要使用的類別是位於哪一個套件
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());
}
}
import的意義
?使用"import"指定時,可於套件指定加上'*' 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());
}
}
import的意義
?可能出現以下的錯誤訊息
bad class file: .\Point2D.java
file does not contain class Point2D
Please remove or make sure it appears in the correct subdirectory of the classpath.
?將原始碼與編譯完成的檔案放在一起並不是一個好的管理方式
javac-d ./classes ./src/*.java
?指定Classpath的方式如下執行程式java -cp ./classes Point2DDemo3
import的意義
?同名衝突
import java.util.Arrays;
import onlyfun.caterpillar.Arrays;
public class SomeClass{
....
}
java.util.Arrays is already defined in a single-type import import onlyfun.caterpillar.Arrays;
^1 error
public與套件
?沒有被宣告為“public”的類別只能被同一個套件中的類別之實例呼叫使用
Point2DDemo.java:3: onlyfun.caterpillar.Point2D is not public in onlyfun.caterpillar; cannot be accessed from outside package
onlyfun.caterpillar.Point2D p1 = new
?類別成員也可以宣告為"public",宣告為"public"的類別成員可以被其它物件呼叫使用
?如果宣告類別時不使用"public"、"protected"或"private"設定權限,則預設為「套件存取範圍」
public與套件
Point2DDemo.java:7: getX() is not public in
onlyfun.caterpillar.Point2D; cannot be accessed from outside package
p1.getX(), p1.getY());
^
public與套件
?類別上的權限設定會約束類別成員上的權
限設定?效果等同於
package onlyfun.caterpillar; class SomeClass{
// ...
public void someMethod() {
// ....
}
}
package onlyfun.caterpillar; class SomeClass{
// ...
void someMethod() {
// ....
}
}
public與套件
?定義一個類別,但沒有定義建構方法時,編譯器會自動幫您產生一個預設建構方法package onlyfun.caterpillar;
public class Test {
....
}
package onlyfun.caterpillar;
public class Test {
public Test() {
}
....
}
public與套件
?如果您自行定義建構方法,則編譯器就不會幫您加上預設建構方法
package onlyfun.caterpillar;
public class Test {
public Test(int i) {
...
}
....
}
?在建構時,就必須指明使用哪個建構方法
public與套件
?建議即使沒有用到,在定義自己的建構方法的同時,也加上個沒有參數的建構方法
package onlyfun.caterpillar;
public class Test {
public Test() { // 即使沒用到,也先建立一個空的建構方法
}
public Test(int i) {
...
}
....
}
?沒有使用super()指定要使用父類別的哪個建構方法,則預設會尋找父類別中無參數的建構方法