修飾外部類別

存取修飾子用於修飾方法時與修飾外部類別時有不同的限制,特別拿出來討論。

假設我們有一個Human類別(Human.java),定義如下:

package tina;
class Human{
    // code...
}// end of class Human

這個Human類別放在套件tina底下,且類別的修飾子為(no modifier,預設),那這個類別只有處於相同套件的類別存取的到。

package tina;
class HumanTest{
    public static void main(String[] args){
        Human h1 = new Human();
    }// end of main(String[])
}//end of HumanTest

這個 HumanTest.java位於套件tina中,可以直接存取到Human這個類別。

但若位在不同套件,就存取不到。

package run;
class Test{
    public static void main(String[] args){
        Human h1 = new Human();  // compile error: Human cannot be resolved to a type
    }// end of main(String[])
}// end of class Test

馬上跳出編譯錯誤的訊息,因為Test類別看不到Human,不知道這是什麼東西。

若要讓不同套件的Test類別要做存取的話,Human必需用public作修飾。

package tina;
public class Human{
    // code...
}// end of class Human

利用public修飾的類別,就算為在不同套件也可以存取的到,只需要import或利用完整類別路徑作存取。 Test.java程式如下:

package run;
import tina.Human;
class Test{
    public static void main(String[] args){
        Human h1 = new Human();           // 有import就可以直接使用
        tina.Human h2 = new tina.Human(); // 利用完整類別路徑也行
    }// end of main(String[])
}// end of class Test

好的,討論完(no modifier)與public修飾子對於類別的影響,那剩下的protected跟private呢?

// 保護
protected class Human{
    // code...
}
// 私有
private class Human{
    // code...
}

很遺憾,這兩個都會編譯錯誤,最外層的類別定義、與檔名同名的那個類別,不能用protected或private修飾。

但是為什麼? why?

protected,用來修飾物件成員,表示可以讓同套件或不同套件但為子類別的類別存取。所以用來修飾類別的話,就是說可以讓同套件或不同套件但為子套件的類別存取。 有沒有覺得很奇怪XD 在Java裡面根本沒有『子套件』這個觀念,所以protected這個關鍵字用在這裡是毫無意義的。

private,用來修是物件成員,表示只有同類別能存取到。但你寫了一個類別檔,卻只有自己可以使用來創造物件? 因此private也不能使用。

在一個檔案定義多個類別:

在一個.java檔中,我們可以定義多個class,方便我們完成所需要的功能。

以Human.java為例;

class Human{
    // code..
}
class Animal{
    // code...
}

這樣是可以的,編譯後會產生Human.class及Animal.class兩個類別檔。

但現在我們要討論修飾子的部份,我們很清楚外部的的類別只能用(no modifier)或public修飾。

以Human.java來說:

public class Human{
    // code...
}
class Animal{
    // code...
}

這是OK的,Human修飾為public可以供不同套件的類別存取,Animal修飾為(no modifier)可以供相同套件的類別存取。

但若寫成這樣:

class Human{
    // code...
}
public class Animal{  //編譯錯誤
    // code...
}

出現編譯錯誤的訊息:The public type Animal must be defined in its own file

也就是說,要用public修飾的外部類別,只能是『與檔名相同』的那個類別。

好,但是為什麼public只能修飾與檔名相同的外部類別呢?

很遺憾的告訴你,因為這是Java規定的。(兇手如下圖↓)

在JLS (Java Language Specification,Java語言規範) 第7.6節提到,

Top Level Type Declarations: (這裡的 Top Level Type就是本章節說的最外層類別)

This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a Java compiler to find a named class within a package. In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.

一個編譯單元(compilation unit,也就是一個 .java檔)最多只能有一個public的修飾,是為了讓Java編譯器更快速的找到套件中的那個類別。

在實務上,很多設計師會將他自己的類別或介面放到屬於那個類別或介面的編譯單元,這種在同一個 .java檔內定義多個外部類別的作法是少見且不建議的。

Last updated