Java 包 (package)

2020-08-15 19:09:55

爲了更好地組織類,Java 提供了包機制 機製,用於區別類名的名稱空間。

包的作用

  • 1、把功能相似或相關的類或介面組織在同一個包中,方便類的查詢和使用。
  • 2、如同資料夾一樣,包也採用了樹形目錄的儲存方式。同一個包中的類名字是不同的,不同的包中的類的名字是可以相同的,當同時呼叫兩個不同包中相同類名的類時,應該加上包名加以區別。因此,包可以避免名字衝突。
  • 3、包也限定了存取許可權,擁有包存取許可權的類才能 纔能存取某個包中的類。

Java 使用包(package)這種機制 機製是爲了防止命名衝突,存取控制,提供搜尋和定位類(class)、介面、列舉(enumerations)和註釋(annotation)等。

包語句的語法格式爲:

package pkg1[.pkg2[.pkg3…]];

例如,一個Something.java 檔案它的內容

package net.java.util;
public class Something{
   ...
}

那麼它的路徑應該是 net/java/util/Something.java 這樣儲存的。 package(包) 的作用是把不同的 java 程式分類儲存,更方便的被其他 java 程式呼叫。

一個包(package)可以定義爲一組相互聯繫的型別(類、介面、列舉和註釋),爲這些型別提供存取保護和名稱空間管理的功能。

以下是一些 Java 中的包:

  • java.lang-打包基礎的類
  • java.io-包含輸入輸出功能的函數

開發者可以自己把一組類和介面等打包,並定義自己的包。而且在實際開發中這樣做是值得提倡的,當你自己完成類的實現之後,將相關的類分組,可以讓其他的程式設計者更容易地確定哪些類、介面、列舉和註釋等是相關的。

由於包建立了新的名稱空間(namespace),所以不會跟其他包中的任何名字產生命名衝突。使用包這種機制 機製,更容易實現存取控制,並且讓定位相關類更加簡單。


建立包

建立包的時候,你需要爲這個包取一個合適的名字。之後,如果其他的一個原始檔包含了這個包提供的類、介面、列舉或者註釋型別的時候,都必須將這個包的宣告放在這個原始檔的開頭。

包宣告應該在原始檔的第一行,每個原始檔只能有一個包宣告,這個檔案中的每個型別都應用於它。

如果一個原始檔中沒有使用包宣告,那麼其中的類,函數,列舉,註釋等將被放在一個無名的包(unnamed package)中。

例子

讓我們來看一個例子,這個例子建立了一個叫做animals的包。通常使用小寫的字母來命名避免與類、介面名字的衝突。

在 animals 包中加入一個介面(interface):

Animal.java 檔案程式碼:

/* 檔名: Animal.java */
package animals;
 
interface Animal {
   public void eat();
   public void travel();
}

接下來,在同一個包中加入該介面的實現:

MammalInt.java 檔案程式碼:

package animals;
 
/* 檔名 : MammalInt.java */
public class MammalInt implements Animal{
 
   public void eat(){
      System.out.println("Mammal eats");
   }
 
   public void travel(){
      System.out.println("Mammal travels");
   } 
 
   public int noOfLegs(){
      return 0;
   }
 
   public static void main(String args[]){
      MammalInt m = new MammalInt();
      m.eat();
      m.travel();
   }
}

然後,編譯這兩個檔案,並把他們放在一個叫做animals的子目錄中。 用下面 下麪的命令來執行:

$ mkdir animals
$ cp Animal.class  MammalInt.class animals
$ java animals/MammalInt
Mammal eats
Mammal travel

import 關鍵字

爲了能夠使用某一個包的成員,我們需要在 Java 程式中明確匯入該包。使用 「import」 語句可完成此功能。

在 java 原始檔中 import 語句應位於 package 語句之後,所有類的定義之前,可以沒有,也可以有多條,其語法格式爲:

import package1[.package2…].(classname|*);

如果在一個包中,一個類想要使用本包中的另一個類,那麼該包名可以省略。

例子

下面 下麪的 payroll 包已經包含了 Employee 類,接下來向 payroll 包中新增一個 Boss 類。Boss 類參照 Employee 類的時候可以不用使用 payroll 字首,Boss 類的範例如下。

Boss.java 檔案程式碼:

package payroll;
 
public class Boss
{
   public void payEmployee(Employee e)
   {
      e.mailCheck();
   }
}

如果 Boss 類不在 payroll 包中又會怎樣?Boss 類必須使用下面 下麪幾種方法之一來參照其他包中的類。

使用類全名描述,例如:

payroll.Employee

import 關鍵字引入,使用萬用字元 「*」

import payroll.*;

使用 import 關鍵字引入 Employee 類:

import payroll.Employee;

注意:

類檔案中可以包含任意數量的 import 宣告。import 宣告必須在包宣告之後,類宣告之前。


package 的目錄結構

類放在包中會有兩種主要的結果:

  • 包名成爲類名的一部分,正如我們前面討論的一樣。
  • 包名必須與相應的位元組碼所在的目錄結構相吻合。

下面 下麪是管理你自己 java 中檔案的一種簡單方式:

將類、介面等型別的原始碼放在一個文字中,這個檔案的名字就是這個型別的名字,並以.java作爲擴充套件名。例如:

// 檔名 :  Car.java
 
package vehicle;
 
public class Car {
   // 類實現  
}

接下來,把原始檔放在一個目錄中,這個目錄要對應類所在包的名字。

....\vehicle\Car.java

現在,正確的類名和路徑將會是如下樣子:

  • 類名 -> vehicle.Car
  • 路徑名 -> vehicle\Car.java (在 windows 系統中)

通常,一個公司使用它網際網路域名的顛倒形式來作爲它的包名.例如:網際網路域名是 runoob.com,所有的包名都以 com.runoob 開頭。包名中的每一個部分對應一個子目錄。

例如:有一個 com.runoob.test 的包,這個包包含一個叫做 Runoob.java 的原始檔,那麼相應的,應該有如下面 下麪的一連串子目錄:

…\com\runoob\test\Runoob.java

編譯的時候,編譯器爲包中定義的每個類、介面等型別各建立一個不同的輸出檔案,輸出檔案的名字就是這個型別的名字,並加上 .class 作爲擴充套件後綴。 例如:

// 檔名: Runoob.java
 
package com.runoob.test;
public class Runoob {
      
}
class Google {
      
}

現在,我們用-d選項來編譯這個檔案,如下:

$javac -d . Runoob.java

這樣會像下面 下麪這樣放置編譯了的檔案:

.\com\runoob\test\Runoob.class
.\com\runoob\test\Google.class

你可以像下面 下麪這樣來匯入所有 *\com\runoob\test* 中定義的類、介面等:

import com.runoob.test.*;

編譯之後的 .class 檔案應該和 .java 原始檔一樣,它們放置的目錄應該跟包的名字對應起來。但是,並不要求 .class 檔案的路徑跟相應的 .java 的路徑一樣。你可以分開來安排原始碼和類的目錄。

<path-one>\sources\com\runoob\test\Runoob.java
<path-two>\classes\com\runoob\test\Google.class

這樣,你可以將你的類目錄分享給其他的程式設計人員,而不用透露自己的原始碼。用這種方法管理原始碼和類檔案可以讓編譯器和java 虛擬機器(JVM)可以找到你程式中使用的所有型別。

類目錄的絕對路徑叫做 class path。設定在系統變數 CLASSPATH 中。編譯器和 java 虛擬機器通過將 package 名字加到 class path 後來構造 .class 檔案的路徑。

\classes 是 class path,package 名字是 com.runoob.test,而編譯器和 JVM 會在 \classes\com\runoob\test 中找 .class 檔案。

一個 class path 可能會包含好幾個路徑,多路徑應該用分隔符分開。預設情況下,編譯器和 JVM 查詢當前目錄。JAR 檔案按包含 Java 平臺相關的類,所以他們的目錄預設放在了 class path 中。