Edited at

「Hello world」を読み解く

More than 1 year has passed since last update.


概要

春なので、初心にかえって 「Hello world」を書いてみました。

皆さんご存じのとおり、「Hello world」は入門用のシンプルなコードです。

しかしその反面、その言語に入門したばかりの初心者には分かりづらい、特徴的な箇所も若干あります。

この投稿では、「Hello world」の特徴的な箇所を解説してみます。

たかが「Hello world」、されど「Hello world」。


HelloWorld.java

まずは、この投稿の主役となるコードを見てください。

ごくごく普通の「Hello world」です。


HelloWorld.java

public class HelloWorld {

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

}



HelloWorld.classの実行結果

hello, world



「Hello world」の特徴的な箇所

それでは、(一般的なJavaプログラムと比べて)「Hello world」の特徴的な記述を見てみましょう。

各項目には私の独断で「特殊度」をつけました。★が多いほど特殊(一般的なプログラムでは見かけない記述)ということになります。


package宣言がない (特殊度: ★★★)

一般的なJavaプログラムはpackage(パッケージ)宣言から始まります。

しかし、HelloWorld.javaには、package宣言がありません。


package宣言の例

package com.example.xyz;


package宣言がないと、クラスは「デフォルトパッケージ」という特殊なパッケージに属することになります。

「デフォルトパッケージ」は「無名パッケージ」と呼ばれることもあります。

「デフォルトパッケージ」に属するクラスは、他のクラスからimport(インポート)することができません。

import宣言では、「パッケージ名を含めたクラス名1」を指定する必要があるからです。


import宣言の例

import com.example.xyz.HelloWorld;



特殊度は?

他のクラスからimportできないクラスは不便なので、「デフォルトパッケージ」はサンプルコードのような使い捨てのコードでしか使いません。

使い捨てでない一般的なプログラムでpackage宣言が存在しないことはまずないので、特殊度は★★★(3)とします。


クラス宣言に、extendsがない (特殊度: ☆☆☆)

Javaでは、すべてのクラスはObjectクラスのサブクラスとなります。

Objectクラスの直接のサブクラスの場合、extends Objectの記述は省略することができます。

つまり、HelloWorldクラスは、Objectクラスの直接のサブクラスとなります。


Objectクラスの直接のサブクラスを宣言する例

// 以下のクラス宣言と全く同じ意味

public class HelloWorld {
// ...
}

// Objectクラスの直接のサブクラスであることを明示
public class HelloWorld extends Object {
// ...
}



特殊度は?

extends Objectをわざわざ明記することは通常ありません2

というわけで、特殊度は☆☆☆(0)です。


mainメソッドが定義されている (特殊度: ★☆☆)

mainメソッドは、特殊なメソッドです。

javaコマンドでは、実行時に指定されたクラスのmainメソッドが呼び出される仕様となっています。

以下、javaコマンドの公式ドキュメントから引用します。


java コマンドは Java アプリケーションを起動します。これは、Java Runtime Environment を起動し、指定されたクラスをロードし、そのクラスの main メソッドを呼び出すことによって行われます。

このメソッドは、public および static として宣言する必要があります。また、値を返してはいけません。さらに、String 配列をパラメータとして指定できなければなりません。メソッド宣言の形式は次のとおりです。

public static void main(String[] args)


上記のとおり、以下がjavaコマンドから呼び出されるメソッドの条件となります。


  • メソッド名が、mainである

  • アクセス修飾子が、publicである


  • static(静的メソッド)である

  • 戻り値が、voidである

  • 引数が、String[](String配列)である

なお、指定されたクラスに呼び出し可能なmainメソッドが存在しない場合、javaコマンドは以下のようなエラーになります。


mainメソッドが存在しない場合のエラー例

> java HelloWorld

エラー: メイン・メソッドがクラスHelloWorldで見つかりません。次のようにメイン・メソッドを定義してください。
public static void main(String[] args)

親切ですね。


特殊度は?

特に特殊な記述というわけではありませんが、規模の大きなプログラムの場合、殆どのクラスはmainメソッドを持ちません。

もしかしたらmainメソッドを使ったことがないJavaプログラマーもいるかもしれない3ので、特殊度は★☆☆(1)としておきます。


「Hello world」の具体的な処理

長くなったので、別投稿にしました。

System.out.println("hello, world")を読み解く


HelloWorld.java(冗長な記述)

ここまでの解説をコードに反映してみました。

コメントも沢山いれたので、読んでみてください。


HelloWorld.java(冗長な記述)

// pacakege宣言を省略することで、このクラスはデフォルトパッケージに所属する

import java.lang.*;
// ※以下、java.langパッケージのクラスはパッケージ名の修飾なしで使用可能だが、例示のためにFQCNで記述する

// このクラスはObjectクラスの直接のサブクラスとなる
public class HelloWorld extends java.lang.Object {

// javaコマンドから呼び出される条件を備えたメソッドを定義する
public // ・アクセス修飾子が、publicである
static // ・static(静的メソッド)である
void // ・戻り値が、voidである
main // ・メソッド名が、mainである
(java.lang.String[] args) // ・引数が、String[](String配列)である
{
// Systemクラスのoutフィールドから、『「標準」出力ストリーム』を取得する
java.io.PrintStream ps = java.lang.System.out;

// Stringインスタンスを、文字列リテラルを使用せずに生成する
char data[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' };
java.lang.String str = new java.lang.String(data);

// printlnメソッドで、strをストリームに出力する
ps.println(str);
}

}



さいごに

さいごにもう一度、普通の「Hello world」を見てみましょう。


HelloWorld.java

public class HelloWorld {

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

}


こうしてみると、「Hello world」から色々と学べることがあるということが分かりました。

たかが「Hello world」、されど「Hello world」。


参考

リンク先がJava7なのは、なんとなく多くの人が使ってそうな気がしたからです。

この投稿の内容自体は、基本的にはどのバージョンでも同様に通用します。





  1. 完全修飾クラス名。「Fully Qualified Class Name」を略して「FQCN」といわれます。 



  2. 私自身、この記事のような「説明用のコード」でしかみたことがないです。 



  3. サーバサイドプログラムやフレームワークを使用している場合など、mainメソッドを記述しなくても動作するプログラムは多々あります。