はじめに
こんにちは。
プログラミング初心者Wakinozaと申します。
Java勉強中に調べたことを記事にまとめています。
十分気をつけて執筆していますが、なにぶん初心者が書いた記事なので、理解が浅い点などあるかと思います。
記事を参考にされる方は、初心者の記事であることを念頭において、お読みいただけると幸いです。
間違い等あれば、指摘いただけると助かります。
対象読者
- Javaを勉強中の方
- Java Silver試験を勉強中の方
- Javaのインポートについてざっくり知りたい方
目次
1. 他パッケージへのアクセス方法
2. インポートの方法
3. オンデマンドインポートと単一型インポート
4. インポートによる名前の衝突
5. Java sliver SE11試験用の補足
本文
1.他パッケージへのアクセス方法
前回、Javaのパッケージについてまとめました。
Javaのパッケージについて再確認したい方は、前回も記事を先に読むことをお勧めします。
これにて、開発中の全てのクラスをパッケージに含めることができたとします。
パッケージがない段階では、別のクラスにアクセスしたい場合、クラス名を指定すれば事足りました。しかしパッケージ後に別パッケージのクラスにアクセスしたい場合、パッケージ名を含めた完全修飾クラス名(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つの条件を揃える必要があります。
「import」と言う名前で勘違いしやすいのですが、インポートは新しい機能を取り込む仕組みではありません。特別な宣言をしなくても、FQCNを記述しすれば、publicなクラスにアクセスできます。importはあくまで、入力を省略するための宣言です。
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)