Java道|import文の使い方

import は、別パッケージのクラスを使いやすくするための案内札です。
長い住所を毎回書かなくても、先に読み込んでおけば、クラス名だけですっきり使えるようになります。

前回までに、異なるパッケージにあるクラスを使うときは、パッケージ名.クラス名 の形で指定することを学びました。

たとえば、pc パッケージにある DemonSlayer クラスを、pb パッケージのクラスから使う場合は、次のように書きます。

pc.DemonSlayer slayer1 = new pc.DemonSlayer();

この書き方は正しいです。
どのパッケージにある DemonSlayer クラスを使っているのかが、はっきり分かります。

ただし、同じクラスを何度も使う場合、毎回 pc.DemonSlayer と書くのは少し長く感じます。

鬼滅の刃風にたとえると、毎回「pc の棚にある DemonSlayer の巻物を使います」と、住所をすべて読み上げているようなものです。

そこで使うのが import 文 です。

import 文を使うと、別パッケージにあるクラスを、ファイルの先頭で「このクラスを使います」と先に宣言できます。
すると、プログラム本体ではパッケージ名を毎回書かずに、クラス名だけで使えるようになります。

import pc.DemonSlayer;

この1行を書いておけば、そのファイルの中では次のように書けます。

DemonSlayer slayer1 = new DemonSlayer();

つまり import 文は、別パッケージのクラスを自分のコード内で使いやすくするための仕組みです。

鬼滅の刃風に言えば、pc の棚にある DemonSlayer の巻物を使うことを、任務開始前にあらかじめ申請しておくようなものです。
申請しておけば、任務中は DemonSlayer と短く呼べるようになります。

import文とは何か

import 文とは、別のパッケージにあるクラスを、現在のソースファイルで使いやすくするための宣言です。

基本の形は次のとおりです。

import パッケージ名.クラス名;

たとえば、pc パッケージにある DemonSlayer クラスを使いたい場合は、次のように書きます。

import pc.DemonSlayer;

これにより、そのソースファイルの中では DemonSlayer という短い名前でクラスを使えます。

書き方意味
pc.DemonSlayerpc パッケージにある DemonSlayer を住所つきで指定する
import pc.DemonSlayer;pc.DemonSlayer をこのファイルで使うことを先に宣言する
DemonSlayerimport 後に使える短いクラス名

import は、クラスをコピーするものではありません。
また、クラスの所属パッケージを変えるものでもありません。

pc.DemonSlayer は、import しても pc パッケージのクラスのままです。
import は、あくまで「このファイルでは pc.DemonSlayer を DemonSlayer と短く書けるようにする」ためのものです。

鬼滅の刃風に考える import のイメージ

鬼滅の刃風にたとえると、パッケージは巻物を整理する棚です。

Java鬼滅の刃風のイメージ
pc パッケージ鬼殺隊士情報を置いている棚
DemonSlayer クラス鬼殺隊士の情報が書かれた巻物
pb パッケージ任務を実行する指令書の棚
Sample6 クラスDemonSlayer を使う任務指令書
import 文別の棚の巻物を使うための事前申請

pb パッケージの Sample6 から、pc パッケージの DemonSlayer を使う場合、何も準備しなければ、pc.DemonSlayer と住所つきで書く必要があります。

しかし、ファイルの先頭で次のように書いておけば、

import pc.DemonSlayer;

main メソッドの中では、DemonSlayer と短く書けます。

これは、任務の最初に「pc の棚にある DemonSlayer の巻物を使います」と申請しておくようなものです。
そのあとは、いちいち pc の棚にあると説明しなくても、DemonSlayer だけで通じるようになります。

importを使わない場合

まず、import を使わない場合を確認します。

異なるパッケージのクラスを使う場合、パッケージ名を含めてクラス名を書く必要があります。

pc.DemonSlayer slayer1 = new pc.DemonSlayer();

この書き方では、型の部分にも pc.DemonSlayer、new の部分にも pc.DemonSlayer と書いています。

部分意味
pc.DemonSlayer slayer1slayer1 は pc パッケージの DemonSlayer 型
new pc.DemonSlayer()pc パッケージの DemonSlayer オブジェクトを作成

この書き方は、どのパッケージのクラスを使っているかが明確です。

ただし、同じクラスを何度も使う場合、毎回 pc.DemonSlayer と書くことになります。

import を使わない場合特徴
pc.DemonSlayer と毎回書くどのクラスかは明確
記述が長くなる何度も出ると読みづらくなる
書き間違いが起こりやすいパッケージ名も毎回書くため

鬼滅の刃風に言えば、毎回「pc の棚にある DemonSlayer の巻物」と正式名称で呼び続けるようなものです。

importを使うとどう変わるのか

import を使うと、ファイルの先頭で使いたいクラスを指定できます。

import pc.DemonSlayer;

この1行を書いておけば、main メソッドの中では次のように短く書けます。

DemonSlayer slayer1 = new DemonSlayer();

import を使う前後を比べると、違いが分かりやすいです。

比較書き方
import なしpc.DemonSlayer slayer1 = new pc.DemonSlayer();
import ありDemonSlayer slayer1 = new DemonSlayer();

import を使うと、コードの中で注目したい処理が見えやすくなります。

DemonSlayer オブジェクトを作る。
show() を呼ぶ。
この流れがすっと読めるようになります。

import の効果内容
記述が短くなるパッケージ名を毎回書かなくてよい
読みやすくなる処理の流れに集中しやすい
管理しやすくなる使う外部クラスを先頭で確認できる
書き間違いを減らしやすい長いパッケージ名を何度も書かなくてよい

import文を書く場所

import 文は、ソースファイルの先頭付近に書きます。

ただし、package 文がある場合は、package 文のあとに import 文を書きます。

今回の Sample6.java では、次の順番になります。

順番書くもの役割
1package pb;このファイルのクラスが pb パッケージに属することを示す
2import pc.DemonSlayer;pc パッケージの DemonSlayer を使うことを示す
3class Sample6実際のクラス定義を書く

コードの形で見ると、次のようになります。

package pb;

import pc.DemonSlayer;

class Sample6
{
}

package 文より前に import 文を書くことはできません。
また、クラス定義の途中に import 文を書くこともできません。

書く位置正しいか
package 文のあと正しい
package 文の前正しくない
class の中正しくない
メソッドの中正しくない

鬼滅の刃風にたとえると、まず「この巻物は pb の棚に置く」と所属を決めます。
そのあとで「pc の棚にある DemonSlayer の巻物を使います」と申請します。
そして最後に、任務の内容を書き始めるイメージです。

package文とimport文の違い

package 文と import 文は、どちらもファイルの先頭付近に書くため、少し混同しやすいです。

しかし、役割はまったく違います。

役割鬼滅の刃風のイメージ
package 文自分のクラスがどのパッケージに属するかを決めるこの巻物をどの棚に置くか決める
import 文別パッケージのクラスを使いやすくする別の棚の巻物を使う申請をする

今回なら、Sample6 クラスは pb パッケージに属します。

package pb;

一方、DemonSlayer クラスは pc パッケージにあります。

import pc.DemonSlayer;

つまり、

クラス所属
Sample6pb
DemonSlayerpc

です。

import pc.DemonSlayer; と書いても、DemonSlayer が pb パッケージに移動するわけではありません。

ここはとても大切です。

importしてもクラスの所属は変わらない

import を書くと、別パッケージのクラスが自分のパッケージに入ってきたように感じるかもしれません。

しかし、実際にはそうではありません。

DemonSlayer クラスは、import しても pc パッケージに属したままです。
Sample6 クラスは、pb パッケージに属したままです。

クラス所属パッケージimport 後
DemonSlayerpcpc のクラスのまま
Sample6pbpb のクラスのまま

import は、クラスの所属を変える仕組みではありません。

import は、別パッケージのクラスを、今書いているファイルの中で短く使えるようにする仕組みです。

鬼滅の刃風にたとえると、pc の棚にある巻物を pb の棚へ移動するわけではありません。
pb の任務指令書から、その巻物を参照しやすくしているだけです。

今回の例で使うファイル構成

今回は、pb パッケージの Sample6 クラスから、pc パッケージの DemonSlayer クラスを使います。

フォルダ構成は次のようになります。

C:\Java\13
        ├─ pb
        │  └─ Sample6.java
        └─ pc
           └─ DemonSlayer.java
ファイルパッケージ役割
pb\Sample6.javapbmain メソッドを持つ実行用クラス
pc\DemonSlayer.javapc鬼殺隊士の情報を表すクラス

↓クリックすると拡大表示されます。

DemonSlayer クラスは、別パッケージから使われるため public にします。

public class DemonSlayer

Sample6.java 側では、ファイルの先頭で import します。

import pc.DemonSlayer;

これにより、Sample6.java の中では DemonSlayer と短く書けます。

import を確認する

ファイル名:Sample6.java

package pb;

import pc.DemonSlayer;

class Sample6
{
    public static void main(String[] args)
    {
        DemonSlayer slayer1 = new DemonSlayer();
        slayer1.show();
    }
}

ファイル名:DemonSlayer.java

package pc;

// 鬼殺隊士クラス
public class DemonSlayer
{
    private String name;
    private String rank;

    public DemonSlayer()
    {
        name = "未登録";
        rank = "階級未設定";
        System.out.println("鬼殺隊士を準備しました。");
    }

    public void setSlayer(String n, String r)
    {
        name = n;
        rank = r;
        System.out.println("隊士名を" + name + "、階級を" + rank + "にしました。");
    }

    public void show()
    {
        System.out.println("隊士名は" + name + "です。");
        System.out.println("階級は" + rank + "です。");
    }
}

実行結果

鬼殺隊士を準備しました。
隊士名は未登録です。
階級は階級未設定です。

この実行結果では、Sample6 から DemonSlayer オブジェクトを作成し、show() を呼び出しています。

DemonSlayer のコンストラクタでは、name に 未登録、rank に 階級未設定 を設定しています。

そのため、show() を呼び出すと、初期状態の隊士情報が表示されます。

Sample6.javaの中心になる部分

このプログラムで特に大切なのは、次の3つです。

package pb;

import pc.DemonSlayer;

DemonSlayer slayer1 = new DemonSlayer();

まず、package pb; によって、Sample6 クラスは pb パッケージに属します。

次に、import pc.DemonSlayer; によって、pc パッケージの DemonSlayer クラスをこのファイルで使いやすくしています。

そして、main メソッドの中では、DemonSlayer とクラス名だけで書いています。

コード意味
package pb;Sample6 は pb パッケージに属する
import pc.DemonSlayer;pc パッケージの DemonSlayer を使う
DemonSlayer slayer1 = new DemonSlayer();import 済みなのでクラス名だけで使える
slayer1.show();DemonSlayer オブジェクトの情報を表示する

import がなければ、main メソッドの中は次のように書く必要があります。

pc.DemonSlayer slayer1 = new pc.DemonSlayer();

import があるため、次のようにすっきり書けます。

DemonSlayer slayer1 = new DemonSlayer();

DemonSlayerクラスはpublicである必要がある

異なるパッケージからクラスを使う場合、利用される側のクラスは public である必要があります。

今回、Sample6 は pb パッケージにあります。
DemonSlayer は pc パッケージにあります。

つまり、Sample6 から見ると DemonSlayer は別パッケージのクラスです。

そのため、DemonSlayer クラスは次のように public にします。

public class DemonSlayer
クラスの指定別パッケージから利用できるか
class DemonSlayer基本的に同じパッケージ内からのみ
public class DemonSlayer別パッケージからも利用できる

また、DemonSlayer のコンストラクタや show() も public にしています。

public DemonSlayer()

public void show()

クラスが public でも、コンストラクタやメソッドが外部から使えない範囲だと、別パッケージから十分に利用できません。

今回のように、別パッケージからオブジェクトを作って show() を呼び出すなら、コンストラクタと show() も public にしておく必要があります。

要素修飾子理由
DemonSlayer クラスpublicpb パッケージから使うため
DemonSlayer() コンストラクタpublicpb パッケージから new するため
show() メソッドpublicpb パッケージから呼び出すため
name フィールドprivate外部から直接変更させないため
rank フィールドprivate外部から直接変更させないため

鬼滅の刃風にたとえると、DemonSlayer の巻物自体は他の棚から閲覧可能にします。
ただし、name や rank のような内部情報は、直接書き換えられないように守っています。

importを使った場合のコンパイル

作業中フォルダが C:\Java\13 の場合、フォルダ構成は次のようになります。

C:\Java\13
        ├─ pb
        │  └─ Sample6.java
        └─ pc
           └─ DemonSlayer.java

コンパイルは、作業中フォルダから行います。

PS C:\Java\13>javac pb\Sample6.java

Sample6.java は pc.DemonSlayer を import しています。

import pc.DemonSlayer;

そのため、pc フォルダの中に DemonSlayer.java があり、DemonSlayer クラスが public であれば、必要に応じてコンパイルされます。

↓クリックすると拡大表示されます。

コンパイル後は、次のようになります。

C:\Java\13
        ├─ pb
        │  ├─ Sample6.java
        │  └─ Sample6.class
        └─ pc
           ├─ DemonSlayer.java
           └─ DemonSlayer.class
ソースファイルコンパイル後
pb\Sample6.javapb\Sample6.class
pc\DemonSlayer.javapc\DemonSlayer.class

↓クリックすると拡大表示されます。

importを使った場合の実行

実行するときは、main メソッドを持つクラスを指定します。

今回、main メソッドを持つのは Sample6 クラスです。

Sample6 は pb パッケージに属しています。

そのため、実行時は次のように書きます。

PS C:\Java\13>java pb.Sample6
コマンド意味
java pb.Sample6pb パッケージの Sample6 クラスを実行する

ここで java Sample6 ではありません。

Sample6 は pb パッケージに属するため、pb.Sample6 と住所つきで指定します。

import pc.DemonSlayer; を書いていても、Sample6 の所属は pb のままです。
そのため、実行時には pb.Sample6 と書きます。

図:importで別パッケージのクラスを使いやすくする

↓クリックすると拡大表示されます。

この図が示していること

この図では、pc パッケージにある DemonSlayer クラスを、pb パッケージの Sample6 クラスから import して使う流れを表しています。

pc パッケージには DemonSlayer.java があります。
DemonSlayer クラスは public なので、別パッケージから利用できます。

pb パッケージには Sample6.java があります。
Sample6.java の先頭で import pc.DemonSlayer; と書くことで、main メソッドの中では DemonSlayer と短く書けるようになります。

要素役割
pc.DemonSlayerpc パッケージにある利用されるクラス
import pc.DemonSlayer;Sample6.java で DemonSlayer を使うための宣言
DemonSlayer slayer1 = new DemonSlayer();import 後の短い書き方
pb.Sample6実行するクラス

この図から分かることは、import はクラスの所属を変えるのではなく、別パッケージのクラスを使いやすくするための仕組みだということです。

図:package文とimport文の役割の違い

↓クリックすると拡大表示されます。

この図が示していること

この図では、package 文と import 文の役割の違いを表しています。

package pb; は、Sample6 クラスが pb パッケージに属することを示します。
つまり、Sample6 自身の住所を決める文です。

一方、import pc.DemonSlayer; は、pc パッケージにある DemonSlayer クラスを、このファイルで使いやすくするための文です。

役割今回の例
package 文自分の所属を決めるSample6 は pb パッケージ
import 文使いたい外部クラスを指定するpc.DemonSlayer を使いやすくする

この図から分かることは、package と import はどちらも先頭付近に書きますが、意味はまったく違うということです。

package は自分の住所を決めるものです。
import は使いたい相手への案内札です。

importを使うときに気をつけたいこと

import は便利ですが、いくつか注意点があります。

注意点内容
利用されるクラスは public が必要別パッケージから使えるようにする必要がある
import は package 文のあとに書く書く順番を守る
import しても所属は変わらないpc.DemonSlayer は pc のクラスのまま
同名クラスがある場合は注意どのクラスを使うか分かりにくくなることがある
import はコードを短くするが、意味を消すわけではない先頭の import を見れば利用クラスが分かる

特に、同じ名前のクラスが複数ある場合は注意が必要です。

たとえば、pa.DemonSlayer と pc.DemonSlayer の両方がある場合、どちらを import するかによって、DemonSlayer と書いたときに指すクラスが変わります。

クラス意味
pa.DemonSlayerpa パッケージの DemonSlayer
pc.DemonSlayerpc パッケージの DemonSlayer

このような場合は、読みやすさのために、あえて pc.DemonSlayer のようにパッケージ名付きで書くこともあります。

importとパッケージ名付き記述の使い分け

import を使う書き方と、パッケージ名付きで書く方法は、どちらも正しい書き方です。

書き方特徴
パッケージ名付きで書くpc.DemonSlayer slayer1 = new pc.DemonSlayer();どのクラスか明確
import して短く書くDemonSlayer slayer1 = new DemonSlayer();コードがすっきりする

同じクラスを1回だけ使うなら、パッケージ名付きで書いても大きな問題はありません。

しかし、何度も同じクラスを使う場合は、import を使ったほうがコードが読みやすくなります。

場面向いている書き方
どのパッケージか明確に見せたいパッケージ名付き
同じクラスを何度も使うimport
同名クラスが複数あって紛らわしいパッケージ名付き
通常の実用的なコードimport を使うことが多い

import は、コードを短くするだけではなく、処理本体を読みやすくするための仕組みでもあります。

importで大切な感覚

import 文で大切なのは、次の感覚です。

考え方内容
package は自分の住所Sample6 は pb パッケージに属する
import は相手への案内札pc.DemonSlayer を使いやすくする
import 後は短く書けるDemonSlayer とだけ書ける
所属は変わらないDemonSlayer は pc パッケージのクラスのまま
public は必要別パッケージから使うには公開されている必要がある

鬼滅の刃風にたとえると、Sample6 は pb の任務指令書です。
DemonSlayer は pc の隊士名簿です。

import pc.DemonSlayer; は、pb の任務指令書から pc の隊士名簿を使いやすくするための案内札です。

案内札があるから、任務本文では DemonSlayer と短く呼べます。
ただし、隊士名簿そのものは pc の棚に置かれたままです。

この感覚がつかめると、import 文はとても自然に理解できます。