21.

Java パッケージ (package) 完全ガイド

編集
この記事の要点
  • package com.example.myapp; はファイル先頭に 1 行で宣言
  • パッケージ名はディレクトリ構造と完全一致 (com/example/myapp/Foo.java)
  • import で他パッケージのクラスを参照、java.lang.* は自動 import
  • package private (アクセス修飾子なし) は同一パッケージ内のみ可視
  • Java 9+ Module System (module-info.java) で公開パッケージを明示制御

package 宣言の基本

// File: com/example/myapp/User.java
package com.example.myapp;

import java.util.List;
import java.util.ArrayList;

public class User {
    private String name;
    public User(String name) { this.name = name; }
}

ルール:

  • package 宣言はファイル先頭に 1 つだけ (コメント / 空行は OK)
  • パッケージ名は ディレクトリ構造と一致 必須
  • 無宣言なら「デフォルトパッケージ」(本番では避ける)
  • 慣習: 全小文字、逆ドメイン (com.example)

ディレクトリ構造とパッケージ

src/
└── main/
    └── java/
        └── com/
            └── example/
                └── myapp/
                    ├── User.java          (package com.example.myapp;)
                    ├── repository/
                    │   └── UserRepo.java  (package com.example.myapp.repository;)
                    └── service/
                        └── UserSvc.java   (package com.example.myapp.service;)

import の書き方

package com.example.myapp.service;

import com.example.myapp.User;                 // 単一クラス
import com.example.myapp.repository.UserRepo;
import java.util.List;
import java.util.Map;

// ワイルドカード (パッケージ直下のクラスのみ。サブパッケージは含まない)
import java.util.*;        // List, Map, ArrayList, ... 全部
// → java.util.concurrent.* は別途必要

// 同名クラスは FQCN (Fully Qualified Class Name) で書く
import java.util.Date;
public class Sample {
    Date a;
    java.sql.Date b;        // FQCN
}

public class UserSvc {
    private final UserRepo repo;
    private final List<User> cache = new ArrayList<>();
}

static import

import static java.lang.Math.PI;
import static java.lang.Math.sqrt;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;   // テストで定番

public class Calc {
    double area(double r) {
        return PI * r * r;          // Math. が省略できる
    }
    double h(double a, double b) {
        return sqrt(a * a + b * b);
    }
}

class CalcTest {
    void test() {
        assertEquals(3.14, PI, 0.01);
        assertTrue(true);
    }
}

java.lang は自動 import

// 以下は import 不要
String s = "hello";          // java.lang.String
Integer i = 0;               // java.lang.Integer
System.out.println(s);       // java.lang.System
new Thread(() -> {}).start(); // java.lang.Thread
new RuntimeException();      // java.lang.RuntimeException
new Object();                // java.lang.Object

アクセス修飾子とパッケージ

修飾子同クラス同パッケージサブクラス他パッケージ
publicOOOO
protectedOOOX
(なし) package privateOOXX
privateOXXX
package com.example.myapp.internal;

class InternalHelper {              // package private (修飾子なし)
    static String secret() { return "hidden"; }
}

// 同じパッケージ内なら見える
package com.example.myapp.internal;
class Other {
    void m() {
        InternalHelper.secret();    // OK
    }
}

// 他パッケージからは見えない
package com.example.myapp.api;
import com.example.myapp.internal.InternalHelper;   // ★ コンパイルエラー

Module System (Java 9+)

// src/main/java/module-info.java
module com.example.myapp {
    // 自分が公開するパッケージ (これ以外は他モジュール from 不可視)
    exports com.example.myapp.api;
    exports com.example.myapp.dto;

    // 内部用は公開しない
    // (com.example.myapp.internal は exports しない)

    // 必要な他モジュール
    requires java.sql;
    requires java.net.http;
    requires com.fasterxml.jackson.databind;

    // リフレクション許可
    opens com.example.myapp.entity to org.hibernate.orm.core;

    // サービス提供 / 利用
    provides com.example.spi.MyService with com.example.myapp.MyServiceImpl;
    uses com.example.spi.MyService;
}

命名規則とディレクトリ設計

パッケージ名含むもの
エントリポイントcom.example.myappMain / Application
コントローラ...myapp.controller or webREST / View
サービス...myapp.serviceビジネスロジック
リポジトリ...myapp.repositoryDB アクセス
エンティティ...myapp.entity or domainJPA / モデル
DTO...myapp.dtoAPI 入出力
設定...myapp.configSpring Config 等
共通...myapp.common / utilユーティリティ
内部...myapp.internal非公開実装

Maven / Gradle でのパッケージ

<!-- pom.xml -->
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0.0</version>

<!-- → ソースは src/main/java/com/example/myapp/ -->
// build.gradle
group = 'com.example'
version = '1.0.0'

// パッケージ名と group は揃えるのが慣例
// → 公開ライブラリでは Maven Central に登録できる

名前衝突を避けるコツ

  • 逆ドメインを使う (com.example)。所有していないドメインは避ける
  • OSS なら io.github.username も慣例 (GitHub 所有を明示)
  • 機能ごとに分割 (com.example.myapp.auth / ...payment)
  • Java 標準 (java.*) や javax.* / jakarta.* と被らない

FAQ

Q: ワイルドカード import (import java.util.*) は使うべき?
A: 1 パッケージから 5 個以上使うなら可。ただし依存が見えにくくなるので明示派が主流。IDE が自動整理してくれる。

Q: パッケージ名と class 名を同じにできる?
A: 技術的には可だが混乱の元。慣習に従い com.example.user.UserService 等にする。

Q: Module System は必須?
A: 必須ではない。ライブラリを公開するなら推奨、アプリ内部だけなら無くても動く。Spring Boot は通常モジュール無し。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本的なルール
  2. データ型
  3. 変数
  4. 定数
  5. 配列
  6. コレクション(List,Set,Queue)
  7. Map(連想配列)
  8. 演算子
  9. 条件分岐
  10. 繰り返し制御文
  11. クラス
  12. メソッド
  13. インスタンス化
  14. コンストラクタ
  15. staticキーワード
  16. オーバーロード
  17. 継承
  18. オーバーライド
  19. this
  20. super
  21. パッケージ
  22. アクセス修飾子
  23. 抽象クラス・メソッド
  24. インターフェース
  25. カプセル化
  26. データベース接続
  27. セッション
  28. ファイル入出力
  29. ラムダ式

最近更新/作成されたページ