📚

Javaの「インポート」をざっくりまとめてみた[Java初心者]

に公開

はじめに

こんにちは。
プログラミング初心者Wakinozaと申します。
Java勉強中に調べたことを記事にまとめています。

十分気をつけて執筆していますが、なにぶん初心者が書いた記事なので、理解が浅い点などあるかと思います。
記事を参考にされる方は、初心者の記事であることを念頭において、お読みいただけると幸いです。
間違い等あれば、指摘いただけると助かります。

対象読者

  • Javaを勉強中の方
  • Java Silver試験を勉強中の方
  • Javaのインポートについてざっくり知りたい方

目次

1. 他パッケージへのアクセス方法
2. インポートの方法
3. オンデマンドインポートと単一型インポート
4. インポートによる名前の衝突
5. Java sliver SE11試験用の補足

本文

1.他パッケージへのアクセス方法

前回、Javaのパッケージについてまとめました。
Javaのパッケージについて再確認したい方は、前回も記事を先に読むことをお勧めします。

https://zenn.dev/wakinoza/articles/23b648416ae9a1

これにて、開発中の全てのクラスをパッケージに含めることができたとします。

パッケージがない段階では、別のクラスにアクセスしたい場合、クラス名を指定すれば事足りました。しかしパッケージ後に別パッケージのクラスにアクセスしたい場合、パッケージ名を含めた完全修飾クラス名(FQCN)を指定しなければなりません。
例として、以下のFQCNを考えてみます。

  • zoo.animal.Dog
  • zoo.animal.Cat
  • zoo.staff.Boss
  • zoo.animal.fry.Bird

同一パッケージに所属しているクラスは、クラス名だけでアクセスが可能です。例えば、上のDogクラスからCatクラスにアクセスしたい場合、クラス名だけでアクセスできます。
しかし、異なるパッケージに所属しているクラスに対しては、クラス名だけではアクセスできません。上のDogクラスとBossクラスは別のパッケージに所属しているので、アクセスする際にFQCNを指定しなければなりません。また、DogクラスとBirdクラスも、サブパッケージが違うため、別パッケージの所属となります。この場合も、互いのアクセスにはFQCNが必要です。

しかし、FQCNをその都度全て記述していると、コードが長くなり、可読性も低下します。
そこでJavaには、入力を簡素化する仕組みが用意されています。
それが、「インポート」です。

2. インポートの方法

インポートは、FQCNの入力を省略するための仕組みです。
package文の下で、かつクラス宣言の上にimport文を宣言します。

package zoo.animal;  

import zoo.staff.Boss;
// import文は、package宣言の下、クラス宣言の前に記述する

public class Dog{  
  //any code
}

「import zoo.staff.Boss」と記述し、「今後『Boss』という表記があったら、『zoo.staff.Boss』のことだよ」と言う指示を出しておくのです。もちろん、省略せずにFQCNを書いても、問題ありません。頻繁に利用するクラスは、import文記述しておくと、FQCNを記述する必要がなくなります。

インポートとは別の領域の話になりますが、別のパッケージへのアクセスで注意点があります。それは、アクセス先クラスのアクセス制御です。
アクセス先のクラスがpublicでない場合は、importやFQCNを記述してもアクセスできません。
他パッケージにアクセスする場合は、①アクセス元がアクセス先のFQCNを正確に記述(もしくはimport)すること、②アクセス先がpublicなクラスであること、この2つの条件を揃える必要があります。

3. オンデマンドインポートと単一型インポート

多くのクラスを利用する場合、1つ1つ全てインポートするのが手間になる時もあります。
Javaには、同じパッケージに所属するクラスをまとめてインポートする仕組みが準備されています。この一括インポートを「オンデマンドインポート」、省略せずにクラス名まで指定するインポートを「単一型インポート」と言います。

オンデマンドインポートの場合、FQCNのクラス名の部分に「*」(アスタリスク文字)を入れます。

import zoo.animal.*;

オンデマンドインポートで「import zoo.animal.*;」と記述した場合、zoo.animalパッケージの全てのクラスを単一型インポートしたことに相当します。

ちなみに、サブパッケージをオンデマンドインポートする仕組みはありません。仮に以下のように記述しても、zooのサブパッケージのクラスはインポートされません。

import zoo.*;

それは、パッケージとサブパッケージに階層関係がないためです。
階層関係がないため、「import zoo.*;」と言う記述は、zoo.animalとは全く別のzooパッケージのオンデマンドインポートと解釈されてしまうのです。そのため、サブパッケージのクラスはオンデマンドインポートできません。

4. インポートによる名前の衝突

インポートは入力を省略できる便利な機能です。
しかし、便利な反面、欠点もあります。
名前の衝突問題が再燃してしまうのです。

同じクラス名が複数あっても、別のパッケージに所属していればFQCNが異なるため、共存できました。
しかし、インポートはパッケージ名を省略する機能です。
もし仮に、別のパッケージに所属する同名のクラスを複数利用したい場合、インポートでパッケージ名を省略してしまうと、区別がつかなくなってしまうのです。
例として、「zoo.animal.Dog」と「family.pet.Dog」の二つを利用したいとします。

import zoo.animal.Dog;
import family.pet.*;

class Cat {
    void do() {
        Dog a = new Dog(); 
        //クラス名だけ記述すると,「zoo.animal.Dog」か「family.pet.Dog」か区別できない
    }
}

上のように2つの同名のクラスをインポートすると、クラス名だけでは区別がつかなくなります。
このような名前の衝突が起きてしまった場合は、どうすればいいのでしょうか。

実はJavaには、利用するクラスに優先順位を設けることで、名前の衝突を解決する仕組みがあります。
その優先順位は以下の通りです。

(1)ソースコード内で宣言したクラスが最優先
(2)次に、単一型インポートしたクラスが優先
(3)その次に、同じパッケージ内のクラスが優先
(4)最後にオンデマンドインポートしたクラス

上のコードで言えば、オンデマンドインポートした「family.pet.Dog」より、単一型インポートした「zoo.animal.Dog」の方が優先されるため、「zoo.animal.Dog」が呼び出されます。

インポートによる名前に衝突を避けるため、①標準ライブラリのクラス名と同名のクラスを作成しないこと、②不必要なオンデマンドインポートを避けること、などを日頃の業務から意識する必要があります。

5. Java sliver SE11試験用の補足

  • Java.langパッケージは、Javaの基本的な動作を提供するパッケージであるため、暗黙的にインポートが行われる仕様になっています。そのため、Java.langパッケージはインポートしなくてもクラス名のみでアクセスできます。

まとめ

  • 別パッケージのクラスを利用したい場合は、FQCNを記述する必要があります。しかし、インポート機能を利用することで入力を省略することができます
  • インポート方法は、クラス名まで指定する「単一型インポート」と、同じパッケージのクラスを一括指定する「オンデマンドインポート」の2つがあります
  • インポートを利用すると、クラス名が衝突する可能性があります。クラスの優先順位を理解しつつ、衝突が起きないように意識したコーディングが必要です

記事は以上です。
次回の更新は、GW後の予定です。
最後までお読みいただき、ありがとうございました。

参考情報一覧

この記事は以下の情報を参考にして執筆しました。

  • [オラクル認定資格教科書 JavaプログラマSilverSE11]
  • [スッキリわかるJava入門 第4版]
  • [パーフェクトJava 改訂3版]
  • [9.1 パッケージとインポート~Java Basic編](最終更新 2023-11-05)(https://qiita.com/KenyaSaitoh/items/d6a55136de5d8f20cd67) (参照 2025-04-24)
GitHubで編集を提案

Discussion