Java/Hello world

出典: フリー教科書『ウィキブックス(Wikibooks)』
Jump to navigation Jump to search
Wikipedia
ウィキペディアHello worldの記事があります。

「Hello world」について[編集]

いよいよJavaのプログラミングを始めましょう。 最初につくるプログラムは「Hello world(ハローワールド)」です。

「Hello world」とは、コマンドプロンプト(ターミナル)の画面上に「Hello, world.」という文字を表示するだけのシンプルなプログラムです。文字を表示するだけですから、プログラム自体に実用的な意味はありません。とりあえず気楽に始めてみましょう。

Hello worldプログラムを通して、次のことを理解することができます。

  • ソースコードの書き方
  • コンパイルの仕方
  • コンパイルしたプログラムの実行の仕方


プログラムを記述する[編集]

まず、お好みのテキストエディタを使って下記のようなプログラムを入力し、保存します。 ファイル名は「Hajimete.java」とします。

public class Hajimete {
    public static void main(String[] args){
        System.out.println("Hello, world.");
    }
}


参考:
ファイルを保存する場所は、原則的にどこでも構いません。しかし、コマンドプロンプト(ターミナル)からアクセスしやすい場所に保存しておくと、後の作業が楽になります。(たとえば、もしWindowsをお使いであれば)C:\srcなどのように、入力するパスが短くて済むようなディレクトリをあらかじめ作っておいて、そこに保存するようにしておくと便利です。


Wikipedia
ウィキペディアバイトコードの記事があります。
Wikipedia
ウィキペディアデバッグの記事があります。


プログラムをコンパイルする[編集]

次にコマンドプロンプト(ターミナル)で、上記のファイルを保存したディレクトリに移動し、次のコマンドを実行します。このコマンドは、上記のプログラムをコンパイルするためのものです。最初の「H」は大文字なので気をつけてください。

javac Hajimete.java

何も表示されなければ、コンパイルが成功したことを意味します。コンパイルの生成物として、今回の場合、カレントディレクトリにHajimete.classというファイルができているはずです。

この、「.class」という拡張子を持つファイルをクラスファイルと呼びます。クラスファイルは、実行ファイルではありません。Javaのソースコードをバイトコードと呼ばれる形式に変換したものです。これを実行するには、後述するjavaコマンドを使う必要があります。


参考:

ディレクトリを移動するには、cdコマンドを使います。もし、Windowsをお使いでHajimete.javaC:\srcディレクトリに保存しているなら、まず

> cd C:\src

を実行してから(先頭の「>」はプロンプトを意味しています。入力はしません)、上記のjavacコマンドを実行します。Hajimete.classが作成されたかどうかは、

> dir 

を実行して確認することができます。

なお、こうしたコマンドプロンプトのコマンドの使い方については、MS-DOS/PC DOS入門で知ることができます。


参考:

もし、クラスファイルが生成されず、何らかのエラーメッセージが表示された場合(すなわち、コンパイルエラーになった場合)は、入力したプログラムに間違いがないかどうかを確認します。コンパイルエラーに対するデバッグは、基本的に表示されたエラーメッセージを手がかりに行いますが、慣れないうちは、メッセージの内容が必ずしも理解しやすいとは限りません。デバッグする際の主な確認ポイントには、たとえば次のようなものがありますので、参考にしてください。

  • 全角文字を使っていないかどうか。上記のプログラムは、すべて半角文字で入力してください。
  • ファイル名が「Hajimete.java」になっているかどうか。「Hajimete.java.txt」などになっていないかどうか。
  • 大文字と小文字を正確に使い分けているかどうか。
  • プログラミング特有の記号類は正しく入力しているか。セミコロン(;)とコロン(:)を間違えていないかどうか、中括弧({ })、角括弧([ ])は正しく入力されているか。

プログラムを実行する[編集]

最後にプログラムを実行します。次のようにコマンドを実行します。

java Hajimete

「Hello, world.」と表示されれば成功です。うまくいきましたか?


参考: コンパイルはうまくいくが、実行ができないという場合

コンパイルは通るのに、実行しようとするとjava.lang.NoClassDefFoundErrorが発生してしまうことがあります。 この原因はクラスパスの指定にあるかもしれません。 Windowsを使っている場合にこの現象が起こる可能性が高いので、ここではWindowsを前提に解説します。

(LinuxUNIXでよく使われるbash, cshシェルについても付随的に説明します。)

まず、コマンドプロンプトから

> echo %CLASSPATH%

(csh/bashの場合)

> echo $CLASSPATH

を実行してみてください。 何らかのパスが表示された場合は、おそらくクラスパスが原因です。

対処する方法は3つあります。


1) まず最初の方法は、クラスパスの指定を消してしまう方法です。

コマンドプロンプトから、

> set CLASSPATH=

(cshの場合)

> setenv CLASSPATH 

(bashの場合)

> export CLASSPATH=

と入力します。これで、クラスパスの設定が消えますから、javaコマンドがカレントにあるクラスを見つけることができるようになります。ただし、次回コマンドプロンプトを立ち上げた際には、また同じことを行う必要があります(つまり、上記の指定は、あくまで現在開いているコマンドプロンプトのウィンドウにだけ適用されるものなのです。次回以降に立ち上げたウィンドウには適用されません)。


2) 次の方法は、javaコマンドのオプションでクラスパスを指定する方法です。

> java Hajimete

の代わりに

> java -cp . Hajimete

と入力します。上記のように「-cp」(または「-classpath」)というオプションの引数に「.」(つまり、カレントディレクトリのこと)が設定すると、クラスパスに「.」が設定された状態でjavaコマンドが実行されます。これでjavaコマンドがクラスを見つけることができるようになります。

このように、-cpオプションで指定した場合、指定されたクラスパスはそのコマンドにのみ適用されます。次回以降に入力されるコマンドには適用されません。


3) 最後の方法は、CLASSPATHの設定に「.」を追加する方法です。

(bashの場合)

> export CLASSPATH=.:$CLASSPATH

(TODO)


上記のように、Javaプログラムを実行するには、javaコマンドを使う必要があります。 javaコマンドの引数には、クラス名(この場合は「Hajimete」)を指定します。javaコマンドは、指定されたクラス名に対応するクラスファイルを読み込み、それをJIT(Just In Time)コンパイラでコンパイルして実行します。つまり、ここでバイトコードは実行形式に変換され、実行できるようになるのです。

Hello worldの解読[編集]

Hello worldの意味を見ていきましょう。


第1行目[編集]

まず最初の行を見てみましょう。

public class Hajimete {

第1行目は、クラスというものを宣言している部分です。

クラスというのはJavaプログラムの基本単位です。「Hajimete」はごく単純なサンプルなので、クラスはこれ1つしかありませんが、ふつうは複数作成し、相互にやりとりさせてプログラムを作ります。


参考:

「クラスとはJavaプログラムの基本単位」という説明をしましたが、この説明だけではもちろんクラスが何であるかを説明できたことにはなりません。読者の中には「クラスが何かよくわからない」と疑問に思っている方も多いかもしれません。

クラスが何であるのかは、後に解説していきます。ここではまだ詳細を理解しようとはせず、まずは、クラスがプログラムを包んでいる「括り」のようなものである点に着目してください。


クラスを記述する基本構文は、次のとおりです。

class クラス名 {
    クラスの実装内容
}
参考:クラスのアクセス修飾子「public」について

ところで、今回のHajimeteの場合、キーワード「class」の前に「public」が付いています。この「public」という語は何でしょうか? これは、アクセス修飾子と呼ばれるもので、このクラスのアクセスレベルを設定するものです。詳細は後述しますが、「public」というは、このクラスが、他のすべてのクラスからアクセス可能であることを表しています。

とはいえ、いまのところ私たちのプログラムにはHajimeteクラス1つしかありません。ですので、アクセス修飾子には特に実用的な意味はありません。

たとえば今回の場合、publicを記述せず、「無指定」というアクセスレベルを設定しても、何も問題はありません(“アクセス修飾子を指定しない”という指定の仕方もあるのです!)。アクセス修飾子については、後述の解説を参照してください。


この基本構文に照らして、今回のHello worldプログラムのクラスを見てみましょう。 まずわかることは、クラス名が「Hajimete」であることです。 というのも、キーワード「class」の次に「Hajimete」が来ているからです。 簡単ですね。

そして、クラスの実装内容を示す「{ }」が、行末から5行目まで(つまりファイルの終端まで)続いていることがわかります。 つまり、今回のHello worldプログラムは、全体をHajimeteという名前のクラスがすっぽりと包んでいるということです。

クラスについて、現時点で注意しておきたいことはこれだけです。 では、さっそく { } の中、つまり2行目以降へと読み進めて、実装内容を見てみることにしましょう。 ──いえ、その前に、もう1つ確認しておきたいことがありました。それは、クラス名と、このソースファイルのファイル名との対応関係です。

今回の場合、クラス名は「Hajimete」です。そして、このプログラムのソースファイル名は「Hajimete.java」でしたね?  このように、Javaでは基本的に、ソースファイルのファイル名を「クラス名+.java」というふうに付けることになっています。


参考:クラス名とファイル名の関係についての補足

もし興味があれば、ソースファイルの名前をまったく別の名前に変えてコンパイルしてみてください。きっとコンパイルエラーになってしまいます。


Wikipedia
ウィキペディアメソッドの記事があります。

第2行目[編集]

続いて2行目を見てみましょう。

    public static void main(String[] args){

この行は、「main」という名前のメソッドを宣言している部分です。 「メソッド」とは、クラスが行う処理のことです。

「Hajimete」はごく単純なサンプルなので、メソッドはこのメソッド1つだけですが、クラスには複数のメソッドを記述することができます。


参考:

メソッドが何であるのかについても詳しくは後述することにします。しかし、もしC言語をご存じであれば、メソッドとはC言語の「関数」に近いものであると考えておいてもよいかもしれません。 つまり、メソッドというものは、何らかのひとまとまりの処理を記述したものです。 そしてやはり関数同様、戻り値を返すしくみをもっています。


メソッドを記述する構文のアウトラインは次のとおりです。

戻り値の型 メソッド名 (引数の型 引数名 ) {
  メソッドの実装内容
}

さて、基本構文に照らして、「Hajimete」の2行目を見てみましょう。 今回の場合、(少しわかりにくいかもしれませんが)「戻り値の型」に当たるのは「void」です(やはりクラス同様、その前に修飾子が付いています。このメソッドの場合「public」と「static」がそれです)。 「戻り値の型」の後に来るのがメソッド名ですから、今回の場合 「main」がメソッド名だということがわかります。


参考:メソッド修飾子について

最初の語「public」は、アクセス修飾子です。アクセス修飾子については、後述します。

次の語「static」は、このメソッドが、staticメソッドというものであることを表しています。staticメソッドとは、そのメソッドが(インスタンスではなく)クラスに属するメソッドであることを表します。これも詳しくは後述します。

なお、publicstaticの2語は、語順を逆に並べることもできます。


そして実装部分は、行末の「{」から4行目の「}」までであることもわかります。 ここで注意すべき点は、メソッドが、クラスの中に記述されている点です。 メソッドというものは、必ずクラスの中に記述されます。クラスの外に直接メソッドを書くことはできません。


参考:

括弧の中に書かれた「String[] args」は、引数です。mainメソッドが、String型の配列String[])を引数に持つことを表しています。argsは引数に与えられた変数名です。

変数や配列、引数などについては、後述します。

なお、この部分は「String args[]」と書くこともできます。また、argsという仮引数は、任意の名前に変えることができます。


さて、実は今回のmainというメソッドには、特記すべきことがあります。

実は、このメソッドのような、

  • アクセスレベルがpublic
  • 引数はString[]を1つだけ取る
  • 名前がmain
  • staticなメソッド

は、特殊な意味を持ち得るのです。すなわち、

$ java Hajimete

のように、javaコマンドで呼び出されたクラスは、自動的に上記のような条件を満たしたmainメソッドを実行することになっているのです。つまり、こうしたmainメソッドは、C言語のmain関数のような役割を果たします。


参考:

ただし、プログラム内にただ1つしか存在し得ないC言語のmain関数とは異なり、mainメソッドを持つクラスがプログラム内に複数あっても構いません。たとえばHajimete.javaに次のようなプログラムを書いたとしても問題はありません。

public class Hajimete {
    public static void main(String[] args) {
        System.out.println("Hello, world.");
    }
}
class Arigatou {
    public static void main(String[] args) {
        Hajimete.main(null);
        System.out.println("Thank you, world.");
    }
}

これをコンパイルして、実行してみましょう。

$ javac Hajimete.java
$ java Hajimete
Hello, world.
$ java Arigatou
Hello, world.
Thank you, world.

mainメソッドが2つあっても、プログラムの実行に問題がない点を確認してください。

なお、ここではArigatouクラスからHajimeteクラスのmainメソッドも呼び出していますが、もちろん必要がなければ呼び出さなくても構いません。あくまで重要なのは、mainメソッドを持つクラスがプログラム内に複数あっても構わないという点です。


参考:

また、mainメソッドの引数であるString[]には、javaコマンドで呼び出された際の引数(コマンドライン引数)が格納されます。少し脱線になりますが、ここでコマンドライン引数を利用した簡単なプログラム例(Echo.java)を見てみましょう。

class Echo {
    public static void main(String[] args) {
        for (String arg: args) {
            System.out.print(arg + " ");
        }
        System.out.println();
    }
}

javacでコンパイルし、実行すると、UNIXのechoコマンドのような動作をします。

$ javac Echo.java
$ java Echo Hello, world
Hello, world
java Echo Hello, world」の「Hello,」と「world」が、Stringの配列の要素として、argsに格納されている点に着目してください。

第3行目[編集]

3行目を見てみましょう。

        System.out.println("Hello, world.");


この行が「Hello, world.」という文字を画面に表示しているところです。つまり、この行に至って、ようやくプログラムの処理にたどり着いたわけです。

Hello worldプログラムは、この処理に至るまで2重に包まれています。 一番外側の包みはクラスです。そして次にメソッドという包みがあります。 これはオブジェクト指向言語の形式を如実に表しています。

もし、BASICでHello worldを書いたならば、

PRINT "Hello, world."

という1行だけで十分だったでしょう。しかし、Javaでプログラミングする場合、BASICのように直接処理を書くことはできません。必ずクラスやメソッドという包みを作り、その上でその中に処理を書きます。これが、Javaプログラミングの最も基本的な作法です。

このページ「Java/Hello world」は、書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にノートへどうぞ。