import 文の全体像
import 文は「他のパッケージにあるクラスやインターフェースを、短い名前で使えるようにする宣言」です。書かなくても「完全修飾名(package.クラス名)」で使えますが、コードが読みにくくなります。import はコンパイル時の名前解決のための仕組みで、実行時の読み込み(クラスパスの探索)とは役割が別です。
基本構文と使い方
最小の書式
import java.util.List; // 1つの型をインポート
import java.util.*; // パッケージ内の「型」を一括(ワイルドカード)
Javapackage 宣言の直後、クラス定義の前に書きます。java.lang は常に自動で見えるため、String や Math に import は不要です。
完全修飾名との対比
// import あり
import java.util.ArrayList;
class Demo {
ArrayList<String> a = new ArrayList<>();
}
// import なし(完全修飾名)
class Demo2 {
java.util.ArrayList<String> a = new java.util.ArrayList<>();
}
Javaimport を使うと、同じファイル内でその型を短い名前で参照できます。処理速度は変わりませんが、可読性が大きく改善します。
パッケージと名前解決(重要ポイントの深掘り)
パッケージ宣言と探索の順序
ファイルの先頭で package com.example.app; のように所属パッケージを宣言します。コンパイラは、参照した型名を次の順で解決します。自分のパッケージ、単純名と同名のクラス、import された型、java.lang、最後に完全修飾名が必要——という流れです。曖昧さがある場合はコンパイルエラーになります。
同名クラスの衝突と回避
異なるパッケージに同名クラスが存在すると衝突します。ワイルドカード import を多用すると増えがちです。解決策は、片方は完全修飾名で書くか、別名使用を避ける設計にすることです。
import java.util.Date;
// import java.sql.Date; // 衝突するため同時に単純名では使えない
class Demo {
Date d1 = new Date(); // java.util.Date
java.sql.Date d2 = new java.sql.Date(System.currentTimeMillis()); // 完全修飾で併用
}
Javaワイルドカード import と static import
ワイルドカード import(パッケージ単位)
import java.util.*; は「パッケージ内のトップレベル型(クラス/インターフェース)」だけが対象です。サブパッケージ(java.util.concurrent など)は含まれません。便利ですが衝突の温床になるため、読みやすさを重視する場面では個別 import を推奨します。
static import(静的メンバーを直接名で呼ぶ)
import static java.lang.Math.*; // Math の静的メンバーを直接使用
class Calc {
double r = sqrt(pow(3, 2) + pow(4, 2)); // Math. を省略
}
Javaテストのアサーションや数学ユーティリティなど、「どのクラスのメンバーかが明白」な場面では有効です。乱用すると出所が分かりにくくなるため、限定的に使います。
import とクラスパスの関係(重要ポイントの深掘り)
役割の違い
import は「名前解決」のための宣言で、コンパイラがソース中の単純名をどの型に対応付けるかを決めます。クラスパス(-cp や IDE 設定)は「コンパイル/実行時にクラスファイルをどこから探すか」を決めます。クラスパスに存在しない型は、import していても見つからずコンパイル/実行に失敗します。
ソース配置とパッケージ整合
パッケージとディレクトリ構造は一致させます。例:package com.example.app; なら、ソースは com/example/app ディレクトリに置くのが基本です。ビルドツール(Maven/Gradle)はこの前提で動きます。
実用例と落とし穴の回避
例 1: List と Map を個別 import で使う
package ex;
import java.util.List;
import java.util.Map;
public class UseCollections {
public static void main(String[] args) {
List<String> names = List.of("sato", "suzuki");
Map<String, Integer> idx = Map.of("sato", 0, "suzuki", 1);
System.out.println(names.get(idx.get("suzuki"))); // suzuki
}
}
Java明示的な import は読み手に優しく、衝突を避けやすくなります。
例 2: static import でアサーションを簡潔に
package test;
import static org.junit.jupiter.api.Assertions.*;
public class CalcTest {
@org.junit.jupiter.api.Test
void pythagoras() {
double c = Math.hypot(3, 4);
assertEquals(5.0, c);
}
}
JavaassertEquals や assertTrue を直接書けるため、テストの意図が際立ちます。
例 3: 同名クラスの併用は片方を完全修飾名で
package ex;
import java.util.Date;
public class BothDates {
Date utilDate = new Date();
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
}
Java衝突を明示的に解消することで、後から読む人にも出所が伝わります。
実務の指針(重要部分のまとめ)
import は「単純名で書けるようにする宣言」であり、実行時読み込みとは別の責務です。ワイルドカードは便利ですが衝突を招きやすく、基本は個別 import を選びます。java.lang は自動可視なので import 不要、サブパッケージは別物として扱うのが前提です。static import は局所的に使い、出所が曖昧にならないよう節度を保ちます。同名衝突は片方を完全修飾名で明示し、パッケージ構造とクラスパスの整合を崩さない。IDE の自動 import は便利ですが、読みやすさと一貫性のために最終的な形は自分の手で整えましょう。
