ソースファイル構成とmainのコードトレース
パッケージを持つRunnerを実際のコマンドで起動する事例です。コンパイルの出力先、クラスパス、mainの宣言、引数配列を一続きで追います。Java SE 17の通常のclass起動を使い、プレビュー機能やソースファイル起動は使いません。
この単元で学ぶこと
- package・import・型宣言の順序を説明できる
- パッケージ付きクラスをコンパイルして起動できる
- mainの宣言と引数の配列から結果を予測できる
本文解説
例のソース Runner.javaへ次を保存します。 package academy; public class Runner { public static void main(String[] args) { System.out.print(args.length); if (args.length > 1) System.out.print(":" + args[1]); } } この型の完全修飾名はacademy.Runnerです。引数の二番目を出す前に、長さが1より大きいかを調べています。
生成物を対応させる javac -d build Runner.javaを実行するとbuild/academy/Runner.classが生成されます。buildは出力のルートであってpackage名ではありません。ルートをclassesへ変えれば生成物はclasses/academy/Runner.classになり、型の完全修飾名は変わりません。
引数を三通り試す java -cp build academy.Runnerなら0、末尾にnorthを一つ指定すると1、north southを指定すると2:southです。main内でprintを使っているので末尾の改行はありません。引数名argsがvaluesでも型とコードを一貫して直せば同じ結果になります。
引用符を含む起動 java -cp build academy.Runner "north south" westでは、通常のシェルは引用符の中の空白を一つの引数内として扱います。配列は二要素で、出力は2:westです。外側の引用符自体は引数の一部として渡りません。引数の分割はJavaのprintlnが後から行う処理ではありません。
探索エラーを作る java -cp build/academy academy.Runnerはルートが深すぎ、標準的なこの配置ではクラスを見つけられません。java -cp build Runnerもpackageを落としているので正しい起動ではありません。ビルド成功と起動指定の正しさは別に確かめます。
入口を変えたとき String[]をString...へ変えた版は入口として使えますが、同時に両方を宣言すると同じ引数型が重複します。main(int n)だけを残す版はメソッドとしてコンパイルできますが、文字列配列の入口がなく通常起動できません。エラーを「コンパイル段階」か「launcherの入口検出」かに分けます。
importの事例 別の例でimport java.util.*;とimport java.sql.*;を書きDateを単純名で使うと曖昧です。java.util.Dateと完全修飾すれば対象を特定できます。またimport java.util.*;だけではjava.util.concurrent.TimeUnitをTimeUnitと短く書けません。packageの階層とimportの対象を別々に追います。
検証の進め方 元のRunnerを生成して三通りの引数を確認してから、-cp、完全修飾名、mainの引数型を一つずつ変えます。各変更後にコンパイルが必要かを判断し、ソース変更なら再生成します。別の試行の古いclassが混ざらない新しい出力ルートを使うと、期待した版が動いているかを確認しやすくなります。
図解
重要ポイント
- package、import、型宣言の順に置く。
- importは名前解決でありコードのコピーではない。
- -cpはパッケージ階層のルートを指定する。
- mainのオーバーロードがすべて起動入口になるわけではない。
間違えやすい点
- java.util.*にサブパッケージが含まれると思わない。
- out/schoolをクラスパスのルートにしない。
- String[]とString...を別の引数型として重複宣言しない。
用語解説
- package
- 型を分類する名前空間。完全修飾名の前半を構成する。
- import
- 型などを短い名前で参照するための宣言。
- 完全修飾名
- パッケージ名を含めた型の名前。例はschool.Main。
- クラスパス
- クラスを探索するためのルートの一覧。
- 可変長引数
- 呼出し時に複数の値を受け取れ、メソッド内では配列として扱う引数。
関連教材
参考資料
教材データに登録された参考リンクです。リンク先の内容や更新日は提供元でご確認ください。
確認問題の出題・採点や学習履歴の保存にはログインが必要です。