※本サイトで紹介している商品・サービス等の外部リンクには、アフィリエイト広告が含まれる場合があります。

こんにちは。こんぶです。
今日は、「パッケージに所属したクラス」について学んでいきましょう!
私の自己紹介等は、こちらからどうぞ。
また、Javaの学習を最初から進めていきたい方は、Java-1から見てみてくださいね。
パッケージに所属したクラス
パッケージに所属したクラスをjavaコマンドで実行する場合は、「java 起動したいクラスの完全限定クラス名(FQCN)」のように指定する必要があります。
例えば、「animal.mammal」というパッケージに所属する「Cat」というクラスを実行する際には「java animal.mammal.Cat」のように指定するということになります。(「java Cat」ではエラーがでます)
なぜ完全限定クラス名(FQCN)を指定するのか
完全限定クラス名(FQCN)を指定する理由は主に3つあります。
- JVMが適切なクラスを見つけられるようにするため
- クラスパスのルールに沿って正しくクラスを検索させるため
- 同じ名前のクラスを区別する必要があるため
1の「JVMが適切なクラスを見つけられるようにするため」は、クラス名だけだとJVMがどのパッケージのクラスなのか判断できないので、完全限定クラス名(FQCN)を指定する必要があるということです。
3の「同じ名前のクラスを区別する必要があるため」は、パッケージには「開発者が自由にクラス名を付けられるようにする」という役割があるからなのですが、その役割については次回詳しく説明します。
2の「クラスパスのルールに沿って正しくクラスを検索させるため」を理解するために、クラスパスについて説明していきます。
クラスパスとは
JVM内部にはクラスローダーというものがあり、指定された完全限定クラス名(FQCN)を持つクラスのクラスファイルをPC内から検索しJVMに読み込んで利用可能にしてくれます。
ここでフォルダの場所は指定していないため、PCのハードディスク内のどこかのフォルダにある該当ファイルを探し出して読み込んでくれます。なぜ一瞬で探し出せるのかというと、クラスパスと呼ばれる情報を参考にしているからです。
クラスパスとは、クラスファイルを格納しているフォルダの場所のことです。
クラスパスの指定方法
クラスパスを指定する方法は3つあります。
1つ目は、javaコマンドでJVMを起動する際に「-cpオプション」または「-classpathオプション」で指定する方法です。javaコマンドで「java -cp クラスパス 完全限定クラス名」もしくは「java -classpath クラスパス 完全限定クラス名」のように指定します。
2つ目は、クラスパスの検索場所をOSの「環境変数」という設定に登録しておく方法です。環境変数に設定しておくと、javaコマンドは自動的に読み込んでクラスファイルの検索に利用してくれます。(環境変数の設定方法はOSによって異なります)
3つ目は、特に指定しない方法です。環境変数や-cpオプション等に指定がない場合は、通常javaコマンドが実行されたフォルダがクラスパスとなります。
クラスパスの指定対象
クラスパスとして指定できるのは、「フォルダの場所」「クラスファイルが入ったJARファイルやZIPファイル」「複数のフォルダやJAR/ZIPファイルの組み合わせ」になります。
複数のフォルダやJAR/ZIPファイルを組み合わせて指定する場合は、デリミタ文字で区切ります。デリミタ文字は、Windowsでは「セミコロン(;)」、macOSやLinuxでは「コロン(:)」です。
クラスローダーは、指定された場所を前から順に探していきます。
クラスファイルの配置
クラスパスを指定して実行しようとしたときに「ClassNotFoundException」というエラーが表示された場合は、目的のクラスファイルを探し出せなかったということです。
パッケージに属したクラスに対するクラスローダーの動作として、パッケージ「a.b.c」に属するクラス「Cat」が対象の場合は「クラスパスで指定されたフォルダ\a\b\c\Cat.class」を探そうとします。
つまり、パッケージに属したクラスファイルをクラスローダーに読み込んでもらうには、現在のクラスパスを基準としてパッケージ階層に対応したフォルダ階層を作り、その中に必要なクラスファイルを配置する必要があるということです。
例えば、パッケージ「a.b.c」に属するクラス「Cat」を正しい配置にするには、現在のクラスパスのフォルダ内に「a」フォルダを作成し、さらにその中に「b」フォルダ、さらにその中に「c」フォルダを作成し、そこに「Cat.class」ファイルを格納するということになります。次の画像のようなイメージです。

現在のクラスパス(c:\test)でコンパイルした後に、cフォルダ(c:\test\a\b\c)にクラスファイルをコピーして格納し、現在のクラスパス(c:\test)で実行するというイメージです。
javacコマンドとjavaコマンドの引数の違い
少し混乱しやすいので、javacコマンドとjavaコマンドの引数の違いについて、整理しておきます。
javacコマンドは、コンパイルするソースファイルのファイル名(.java)を引数として指定して実行することで、Javaのソースコードをバイトコード(.class)に変換します。
javaコマンドは、起動したいmainメソッドを含むクラスの完全限定クラス名(FQCN)を引数として指定して実行することで、コンパイル済みのバイトコード(.class)を実行してくれます。
2つの違いについて、しっかり理解しておきましょう。
今回のまとめ
★パッケージに所属したクラスをjavaコマンドで実行する場合、「java 起動したいクラスの完全限定クラス名(FQCN)」のように指定する
★javaコマンドで「-cpオプション」または「-classpathオプション」でクラスパスを指定できる
★「複数のフォルダやJAR/ZIPファイルを組み合わせたもの」をクラスパスとして指定する場合は、デリミタ文字で区切る
★デリミタ文字は、Windowsはセミコロン(;)、macOSやLinuxはコロン(:)
★パッケージに属したクラスファイルを実行するには、現在のクラスパスを基準としてパッケージ階層に対応したフォルダ階層を作り、その中に必要なクラスファイルを配置する必要がある
★javacコマンドは、ファイル名(.java)を引数として指定することで、Javaのソースコードをバイトコード(.class)に変換する
★javaコマンドは、完全限定クラス名(FQCN)を引数として指定することで、コンパイル済みのバイトコード(.class)を実行する
・クラスローダー:JVM内部にあり、指定されたクラスファイルをJVMに読み込んで利用可能にする役割をもつもの
・クラスパス:クラスファイルを格納しているフォルダの場所
次回は、「パッケージの役割(クラス名)」について説明していこうと思います。
今回の内容のチャレンジ問題はこちらです→チャレンジ問題【Java-33】~パッケージに所属したクラス~
次の内容に進む方はこちらです→【Java-34】パッケージの役割(クラス名)
それでは、こんぶはじゃ~
コメント