Java | 基礎文法:パッケージ

Java Java
スポンサーリンク

パッケージの全体像

パッケージは「クラスを論理的にグループ化し、名前が衝突しないようにする仕組み」です。ファイルの先頭に package com.example.app; のように宣言し、ディレクトリ構造と一致させます。利用側から見ると「完全修飾名(例:com.example.app.User)」で一意にクラスを指せるようになり、大規模開発でも整理と再利用がしやすくなります。


基本構文とディレクトリ配置

パッケージ宣言とクラス定義

// src/main/java/com/example/app/User.java
package com.example.app;

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

package はファイル先頭に1回だけ書きます。省略すると「デフォルトパッケージ」になりますが、実務では推奨されません(import やアクセス制御が不便になり、ビルドツールとの相性も悪くなります)。

ディレクトリ構造との一致

src/main/java/
└── com/
    └── example/
        └── app/
            └── User.java

パッケージ名はディレクトリの階層に直結します。ビルドやクラスパスの探索はこの前提で動くため、「宣言と置き場所の不一致」はコンパイルや実行で失敗の原因になります。


import と完全修飾名の使い分け(重要ポイントの深掘り)

別パッケージからの利用

// src/main/java/com/example/Main.java
package com.example;

import com.example.app.User; // 短い名前で使う宣言

public class Main {
    public static void main(String[] args) {
        User u = new User("sato");    // import で短く書ける
        com.example.app.User u2 = new com.example.app.User("suzuki"); // 完全修飾名でも可
        System.out.println(u.name + ", " + u2.name);
    }
}
Java

import は「ソースコード内で単純名を使えるようにする」宣言です。なくても完全修飾名で書けますが、可読性が落ちます。java.langString, Math など)は常に見えるため import 不要です。

同名クラスの衝突を明示的に解決

異なるパッケージに同名クラス(例:java.util.Datejava.sql.Date)がある場合、片方は import、もう片方は完全修飾名にして衝突を避けます。ワイルドカード import の多用は衝突の温床になるため、基本は個別 import を選びます。


アクセス修飾子とパッケージ境界(重要ポイントの深掘り)

可視性のルール

package com.example.lib;

public class PublicApi { /* どこからでも見える */ }

class InternalHelper { /* 同パッケージ内のみ(package-private) */ }
Java
  • public: どのパッケージからも参照可能。ライブラリの公開 API。
  • package-private(修飾子なし): 同じパッケージからのみ参照可能。内部ヘルパーに適切。
  • protected: 同パッケージ+サブクラスから参照可能(継承前提の設計向け)。
  • private: クラス内のみ。

「外に見せる最小限だけ public、内部は package-private で隠す」が基本設計です。パッケージを「モジュールの境界」として意識すると、変更に強くなります。


命名規約と設計指針

パッケージ名の付け方

逆ドメイン名 + プロジェクト + 機能
例:com.company.project.user、org.example.util.text
Java
  • すべて小文字、短くわかりやすく。
  • 組織やアプリの単位から階層化し、機能単位で細分化。
  • 省略形や曖昧な名前(utils, common だけ)は避け、具体性を持たせる。

デフォルトパッケージは避ける

package を省略した「デフォルトパッケージ」は、クラスパスやツール連携で扱いづらく、他パッケージから参照も不便です。学習用の小さなサンプル以外では必ずパッケージを宣言します。


実用例で身につける

例 1: 複数パッケージで役割分離

// src/main/java/com/example/app/model/User.java
package com.example.app.model;
public record User(String name, int age) {}

// src/main/java/com/example/app/service/UserService.java
package com.example.app.service;
import com.example.app.model.User;
public class UserService {
    public boolean isAdult(User u) { return u.age() >= 18; }
}

// src/main/java/com/example/App.java
package com.example;
import com.example.app.model.User;
import com.example.app.service.UserService;
public class App {
    public static void main(String[] args) {
        var u = new User("sato", 20);
        var svc = new UserService();
        System.out.println(svc.isAdult(u)); // true
    }
}
Java

モデルとサービスをパッケージで分けることで、依存方向と役割が明確になります。

例 2: 内部実装を隠す(package-private)

// src/main/java/com.example.calc/Adder.java
package com.example.calc;
public class Adder {
    public int add(int a, int b) { return Internal.add(a, b); }
}
class Internal { // 外部から見えない
    static int add(int a, int b) { return a + b; }
}
Java

外に見せる API を絞り、内部実装は同パッケージ内に閉じ込めます。差し替えや最適化がしやすくなります。

例 3: テストと本体の配置(参考)

src/main/java/com/example/...
src/test/java/com/example/...

テストは本体と同じパッケージに置くと、package-private な内部にアクセスできます。Junit などのテストフレームワークとの相性も良くなります。


仕上げのアドバイス(重要部分のまとめ)

パッケージは「構造と境界」。宣言とディレクトリを一致させ、役割ごとに階層化します。公開は最小限(public)、内部は package-private で隠す。import は個別指定を基本にして衝突を避け、完全修飾名で明示的に併用する判断軸を持つ。デフォルトパッケージは使わず、逆ドメイン+機能で小文字の明確な命名に統一する——この設計を守れば、規模が大きくなっても読みやすく安全な構成を保てます。

タイトルとURLをコピーしました