インドリさんの助言に従い、今度はコマンドプロンプトからのコンパイルを試してみる。
これは、IDE の裏でコンパイラがどう動いているかを実感するのが目的。
C++ でもコンパイラやリンカの動きを想像してたらバグが見つかったなんてこともあったので、少なくとも芸の肥やしくらいにはなるだろう。
さてコマンドプロンプトからのコンパイル方法をぐぐってみたら、下記のページがヒットした。
Howdy, Java!
ふーん、なるほど。
コンパイラは javac で、ソースコードの拡張子は .java ね。
んじゃとりあえず、コマンドプロンプトで "javac" と叩いてみる。
'javac' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
えーと、えーと。"java" はそれなりの答えを返してくれたところをみると、インストールそのものはできていると思う。
ということは、自力で環境変数を設定しないといけない?
そう思ってぐぐったら、確かにその通りだった。
Step5・Java 環境変数のPathを設定
おーけーおーけー、んじゃ設定しよう。
やることはシステムのプロパティを使ってシステム環境変数 "Path" の最後に javac のディレクトリを追加するだけ。
ちなみに私の環境では、javac.exe は "C:\Program Files\Java\jdk1.6.0_12\bin" にある。
パスを通して再起動したら、ヘルプを返してくれた……って、日本語化されてる。これはありがたい。
んじゃ、先ほど作った Hello world! をテキストエディタで作り直してみる。
public class HelloWorld
{
public static void main( String[] args )
{
System.out.println( "Hello world!" );
}
}
んでカレントディレクトリをソースコードディレクトリに移して、コマンドプロンプトから "javac hello.java" と叩いてみる。
hello.java:1: クラス HelloWorld は public であり、ファイル HelloWorld.java で宣
言しなければなりません。
……。Javaって、 public なクラスはクラス名と同じ名前のファイルで定義しないとダメなの?
そう思って先ほどのファイルを "HelloWorld.java" にリネームしてからコンパイルしたら、今度は正しくコンパイルされた。
ここでふと気がついた。
Java って、ネームスペースとフォルダ構成を一致させないといけないのか?
もしそれが保証されているとしたら、ゲートになるソースファイルを食わせるだけで、コンパイラはすべてのソースファイルを取得することができるはず。
ということは、プロジェクトファイルが必要なくなるんじゃないだろうか。
ちょっとおもしろそうなので上記については後で検証しておこう。
これが本当なら、いろいろと考察が広がりそうだし。
さてコンパイルした結果を見てみると、ソースファイルと同じディレクトリに .class ファイルができている。
これを java.exe に食わせれば、コマンドプロンプトに "Hello world!" と表示されるはず。
ということでコマンドプロンプトで "java HelloWorld" と叩いてみると、
Hello world!
と表示された。
※ CLASSPATH の設定をせずとも正常に動作しました。java.exe のオプションで、クラス名を小文字で指定したのがエラーの原因だったようです。
以下、恥さらし。
Exception in thread "main" java.lang.NoClassDefFoundError: helloworld (wrong nam
e: HelloWorld)
(中略)
Could not find the main class: helloworld. Program will exit.
あっるぇ~?
メインクラスが見つからないって、ちゃんと main メソッド書いたよ?
ぐぐったら同じような問題を抱えている人は多いようで、いくつもヒットした。
その中でも気になったのが、以下の投稿。
「Could not find the main class」の回避方法
環境変数 CLASSPATH ねぇ。
カレントディレクトリの .class ファイルを指定してるから、あんまり関係ないと思うけどなぁ。
そう思ってさらに検索してみると、下記で「カレントワーキングディレクトリ」なる単語を見つけた。
Java 環境のセットアップ
……。つまり、カレントディレクトリの .class ファイルを実行するにも CLASSPATH の指定が必要と?
上記ページの下の方に問題の切り分けに関する記述があって、そこにオプションでクラスパスを指定する方法が書かれていた。
ということで、試しに "java -classpath . HelloWorld" と打ってみる。
Hello world!
正解だったらしい。
この後 CLASSPATH に ".;" を定義して再起動したら、 "java HelloWorld" でも想定通りに動作した。
しかしデフォルトでカレントディレクトリを検索しないって、どういう意味があるんだろう?
何となく思想のようなものが透けて見える気がするけど、いまのところはよくわかんない。
以上のまとめとか雑感とか。
- Java のソースファイルの拡張子は .java。
- public なクラスは、同じファイル名のソースファイルで定義しなければならない?
- Java のコンパイラは javac.exe。
- コンパイルすると、 .class ファイルが生成される。これが Java の実行ファイル。
- JDK をインストールしただけでは、コマンドラインツールを使用するのに不便。環境変数を設定すること。
- PATH に javac.exe のパスを指定する。
CLASSPATH に ".;" を指定する。
最後の ";" は必要ないと思うが、後のことを考えて付けておく。
- java.exe にクラスを指定すると実行できる。
- java.exe に食わせるのは「クラス」であって「.class ファイル」ではない。
- 従って、Windows 環境であっても大文字小文字を厳密に区別する。
- .class ファイルのフルパスを指定するのは無意味。そもそも、食わせるのはファイルではない。
環境変数 CLASSPATH に "." が指定されていない場合、たとえカレントディレクトリに .class ファイルがあってもオプションなしでは実行できない。
※ ↑間違い。設定せずともカレントディレクトリの .class ファイルを実行することができます。
- CLASSPATH に指定されていない場所の .class ファイルを実行するには、 -classpath オプションを利用する。-cp も同じ意味。
- -classpath オプションはクラスの検索位置を指定するためのもの。従って "java -classpath .HelloWorld" なんてやると蹴られる。
- ↑"." と "HelloWorld" の間にスペースがないのがエラーの原因。