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



## はじめに

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

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

## 対象読者

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

## 目次

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

## 本文

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

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

https://qiita.com/wakinoza/items/db55bacc88789471f270

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

パッケージがない段階では、別のクラスにアクセスしたい場合、クラス名を指定すれば事足りました。しかしパッケージ後に別パッケージのクラスにアクセスしたい場合、パッケージ名を含めた完全修飾クラス名（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文を宣言します。

```Java
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つの条件を揃える必要があります。

:::note info
「import」と言う名前で勘違いしやすいのですが、インポートは新しい機能を取り込む仕組みではありません。特別な宣言をしなくても、FQCNを記述しすれば、publicなクラスにアクセスできます。importはあくまで、入力を省略するための宣言です。
:::

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

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

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

```Java
import zoo.animal.*;
```

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

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

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

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

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

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

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

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

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

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

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

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

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


### 5\. Java sliver SE11試験用の補足

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


## まとめ

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

---------------

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

##  参考情報一覧

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

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