こんにちは、かつコーチです。
「import java.util.List;って毎回書いているけど、これって何をしているの?」と疑問に思ったことはありませんか。
Javaのパッケージ(クラスをグループ分けして管理する仕組み)とimport(他のパッケージのクラスを使うための宣言)は、規模の大きいプログラムを整理するために欠かせない仕組みです。
この記事では、パッケージとimportの役割を、実際にディレクトリ構成を確認しながら解説します。
パッケージとimportとは
クラスをグループ分けして管理する仕組み
パッケージとは、関連するクラスをフォルダのようにグループ分けして管理する仕組みです。
Javaの標準ライブラリも、java.util(コレクションなどのユーティリティ)、java.io(入出力)、java.time(日付時刻)のようにパッケージで整理されています。
パッケージ名は、クラスファイルの先頭にpackage文で宣言します。
package com.example.myapp;
public class User {
// ...
}
パッケージ名は、実際のディレクトリ構造と一致させる必要があります。
上記のUserクラスは、com/example/myapp/User.javaというパスに配置します。
なぜパッケージ分けが必要なのか
パッケージ分けには、主に2つの目的があります。
- 名前の衝突を防ぐ:同じクラス名(例:
User)が別の機能で必要になっても、パッケージが違えば共存できる - 関連するクラスをまとめて見通しをよくする:機能ごとにフォルダを分けることで、どこに何があるか把握しやすくなる
小規模な学習用コードでは意識しにくいですが、実務でクラス数が増えてくると、パッケージ分けの有無で保守のしやすさが大きく変わります。
基本の書き方・実装手順
手順1:パッケージを宣言する
パッケージを使う場合、ファイルの先頭(コメントを除く1行目)にpackage文を書きます。
// src/com/example/model/User.java
package com.example.model;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
手順2:importで他のパッケージのクラスを使う
別のパッケージにあるクラスを使う場合は、import文で宣言します。
// src/com/example/Main.java
package com.example;
import com.example.model.User;
public class Main {
public static void main(String[] args) {
User user = new User("田中");
System.out.println(user.getName()); // 田中
}
}
importを書くことで、コード中にcom.example.model.Userと完全な名前を書かなくても、Userだけで参照できるようになります。
手順3:標準ライブラリのimport
Javaの標準ライブラリを使う場合も同じ仕組みです。
import java.util.ArrayList;
import java.util.List;
public class Sample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("佐藤");
System.out.println(names);
}
}
なお、java.langパッケージ(String、Systemなど)だけは、import文を書かなくても自動的に使えるようになっています。
つまずきやすい設定・注意点
package文は、ファイルの実質1行目(コメントを除く)に書く必要がある- パッケージ名は慣習として、すべて小文字+ドット区切りにする(例:
com.example.myapp) - 1つのファイルに書ける
package文は1つだけ
よくあるつまずきポイント・エラー対処
ディレクトリ構造とパッケージ名が一致していない
初心者が最初につまずきやすいのが、パッケージ名の宣言と、実際のファイルの配置場所がずれているケースです。
❌Before
src/
User.java ← com.example.modelパッケージのつもりだが、直下に置いてしまった
// src/User.java
package com.example.model;
public class User {
}
このままコンパイルすると、環境によっては次のようなエラーになります。
error: class User is public, should be declared in a file named User.java
または、コンパイルは通ってもクラスパスの解決時にClassNotFoundExceptionが発生することがあります。
私が実際にこのエラーに遭遇したのは、IDEを使わずコマンドラインでjavacを実行していたときでした。
パッケージ宣言とディレクトリ構造がずれていると、コンパイラやJVMがクラスを正しく見つけられません。
✅After
src/
com/
example/
model/
User.java ← package com.example.model; と一致させる
パッケージ名のcom.example.modelは、com/example/model/というディレクトリ構造に対応させる必要があります。
IntelliJ IDEAなどのIDEを使っていれば、パッケージ作成時に自動でディレクトリも作られるため、このズレは起きにくくなります。
同名クラスのimportで衝突する
異なるパッケージに同名のクラスがある場合、両方をimportしようとするとコンパイルエラーになります。
import java.util.Date;
import java.sql.Date; // コンパイルエラー:同名クラスの重複import
このような場合は、片方だけをimportし、もう一方は完全修飾名(パッケージ名を含めたフルネーム)で直接記述します。
import java.util.Date;
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
応用・一歩先の使い方
ワイルドカードimportは避けるのが基本
import java.util.*;のように*を使うと、パッケージ内の全クラスを一括でimportできます。
ただし、どのクラスが実際に使われているか分かりにくくなるため、実務ではIDEの自動import機能を使い、必要なクラスだけを個別にimportするのが一般的です。
まとめ
この記事のポイント
- パッケージはクラスをグループ分けして管理する仕組みで、名前の衝突防止と見通しの良さに役立つ
package文はファイルの実質1行目に書き、ディレクトリ構造と一致させる必要があるimport文で他のパッケージのクラスを完全な名前なしで参照できるようになるjava.langパッケージだけはimport不要で自動的に使える
次に読むべき記事
- クラス自体の作り方をまだ確認していない方は、次章のクラスとオブジェクトの基本の記事もあわせてご覧ください
- staticキーワードの意味については、次の記事で解説します
タグ: Java, 初心者向け, 基本文法