Java開発は経験があっても、パッケージ構成は決まっている状態から新規実装や改修しかしたことがないという開発者の方も多いのではないでしょうか。
本記事では、Javaアプリ開発の初期で検討するパッケージ構成の基本についてご紹介していきます。
Javaのパッケージ構成とは
Java開発ではルートパスからパッケージ階層を決定し、配下にクラスファイルを格納していくことになりますが、このパッケージ階層の切り分けがパッケージ構成と呼ばれます。
パッケージ名の命名規則
パッケージ名の命名規則としては、一般的に全て小文字で設定しハイフンは使わず全てアンダースコアで作成します。
またルートとなるパッケージ名は、インターネットドメインを逆さにしたパッケージ名を付けることが多いようです。
ポテパンスタイルを例にするとドメイン名が「style.potepan.com」なので、パッケージ名は「com.potepan.style」となります。
Javaパッケージのよくある構成
パッケージ構成はプロジェクトで自由に決めることが出来るため、これといった決まりはありません。
ただ自由に決められるとはいっても、多くのプロジェクトで用いられているような構成は存在します。
あくまで一例ですが、「application」と「domain」に切り分けて、下の階層にいくつかのパッケージを作る構成などがあげられます。
$ tree . ├── application │ ├── controller │ └── resource ├── domain │ ├── entity │ ├── object │ ├── repository │ └── service
Javaのパッケージ構成とアクセス制限の関係性
Javaでのパッケージ構成は、ただ単にファイルの格納先を分別するだけでなく、クラスファイルへアクセスする際の方法や宣言方法にもルールがあるので確認しておきましょう。
パッケージ宣言
パッケージに格納されたフォルダは、Javaファイルの先頭でパッケージを宣言する必要があります。
package パッケージ名[.パッケージ名・・・];
パッケージの宣言は「package」文を記述し、階層化させる場合には「.」で繋げてパッケージ名を記述します。
パッケージ構成を下記で定義している場合の「SampleController.java」の宣言方法について見てみましょう。
src % tree . └── com └── potepan └── style ├── application │ ├── controller │ │ └── SampleController.java │ └── resource └── domain ├── entity ├── object ├── repository └── service 11 directories, 1 file
このような階層になっている場合、宣言は下記の記述となります。
package com.potepan.style.application.controller;
ちなみにパッケージ宣言のパスと、実際のパスが異なる場合にはコンパイルエラーとなるため注意が必要です。
パッケージ宣言されたファイルの呼び出し方
パッケージ宣言されたクラスファイルを利用する側のプログラムからは、パッケージとの関係やクラス名により呼び出し方が変わってきます。
今回のサンプルでは下記のパッケージ構成でご紹介していきます。
src $ tree . └── com └── potepan └── style ├── Main.java ├── TestController.java ├── application │ ├── controller │ │ ├── SampleController.java │ │ └── TestController.java │ └── resource └── domain ├── entity ├── object ├── repository └── service └── SampleService.java 11 directories, 5 files
同一パッケージ内
同一パッケージ内にアクセスしたいクラスファイルがある場合、クラス名を指定するだけでアクセスが可能となります。
サンプルでは、controllerパッケージ配下の「SampleController.java」から「TestController.java」にアクセスしてみます。
SampleController.java
package com.potepan.style.application.controller; public class SampleController { public static void testController() { TestController.testController(); } }
TestController.java
package com.potepan.style.application.controller; public class TestController { public static void testController() { System.out.println("TestControllerから出力"); } }
SampleController側では、シンプルにTestControllerのメソッドを呼び出すだけでアクセス出来ていることが分かります。
同一パッケージ外
次は異なるパッケージに格納されたクラスファイルにアクセスしたい場合を確認してみましょう。
サンプルではcontrollerパッケージ配下の「SampleController.java」から、serviceパッケージ配下の「SampleService.java」へアクセスしてみます。
SampleController.java
package com.potepan.style.application.controller; import com.potepan.style.domain.service.SampleService; public class SampleController { public static void testController() { SampleService.testService(); } }
SampleService.java
package com.potepan.style.domain.service; public class SampleService { public static void testService() { System.out.println("SampleServiceから出力"); } }
SampleController側の3行目にimport文が追加されているのが確認出来ます。
別パッケージの場合には、import文によりアクセスしたいクラスファイルのパッケージを指定してあげる必要があります。
同一クラス名
最後に同一クラス名のファイルが複数パッケージに存在する場合のアクセス方法を確認しておきましょう。
SampleController.java
package com.potepan.style.application.controller; public class SampleController { public static void testController() { TestController.testController(); com.potepan.style.TestController.testController(); } }
TestController.java(同一パッケージ)
package com.potepan.style.application.controller; public class TestController { public static void testController() { System.out.println("TestControllerから出力"); } }
TestController.java(別パッケージ)
package com.potepan.style; public class TestController { public static void testController() { System.out.println("同一クラス名はパッケージ名からのフルパスで指定します。"); } }
SampleControllerの7行目に記述しているように、import文では同一パッケージの同名クラスか別パッケージかどちらを呼び出しているのか分からないため、パッケージをフルパスで指定してあげる必要があります。
さいごに: Javaのパッケージ構成を理解して適切にクラスを管理しよう
本記事では、Javaのパッケージ構成に関する基本的な情報から実際の使い方についてサンプルコードを掲載しながらご紹介してきました。
近年のIDEでは、自動的にパッケージが補完されることも少なくないため、あまり意識せずとも特に問題なかった方も多いかも知れません。
しかし同名クラスのように意図しない呼び出しを防ぐためにも、パッケージ構成をしっかりと把握してアプリ開発を進められるように知識として定着させましょう。
import文を利用しない場合は、ソースコード内で毎回パッケージパスを全て記述してあげる必要があります。