2.1 Javaプログラムの基本と"Hello, World!"～Java Basic編

### はじめに

#### 自己紹介

皆さん、こんにちは、Udemy講師の斉藤賢哉です。私はこれまで、25年以上に渡って企業システムの開発に携わってきました。特にアーキテクトとして、ミッションクリティカルなシステムの技術設計や、Javaフレームワーク開発などの豊富な経験を有しています。
様々なセミナーでの登壇や雑誌への技術記事寄稿の実績があり、また以下のような書籍も執筆しています。
* [「マスタリング Java EE 5」（2007年）](https://amzn.asia/d/j0txqK5)
* [「アプリケーションアーキテクチャ設計パターン」（2017年）](https://amzn.asia/d/9avaCyF)

いずれも**Java EE**（**Jakarta EE**）を中心にした企業システム開発のための書籍です。中でも [「アプリケーションアーキテクチャ設計パターン」](https://amzn.asia/d/9avaCyF)は、（Javaに限定されない）比較的普遍的なテーマを扱っており、内容的にはまだまだ陳腐化していないため、興味のある方は是非手に取っていただけると幸いです（中級者向け）。

#### Udemy講座のご紹介

この記事の内容は、私が講師を務めるUdemy講座『**Java Basic編**』の一部の範囲をカバーしたものです。『**Java Basic編**』はこちらの[**リンク**](https://www.udemy.com/course/learn-java-se-basic/?referralCode=594C958456356851C97C)から購入できます（セールス対象外のためいつも同じ価格）。また**定価の約30%OFFで購入可能なクーポン**をQiita内で定期的に発行していますので、興味のある方は、ぜひ私の他の記事をチェックしてみてください。

この講座は、以下のような皆様にお薦めします。
* Javaの言語仕様や文法を正しく理解すると同時に、現場での実践的なスキル習得を目指している方
* 新卒でIT企業に入社、またはIT部門に配属になった、新米システムエンジニアの方
* 長年IT部門で活躍されてきた中堅層の方で、学び直し（リスキル）に挑戦しようとしている方
* 今後、フリーランスエンジニアとしてのキャリアを検討している方
* 「**Chat GPT**」のエンジニアリングへの活用に興味のある方
* 「**Oracle認定Javaプログラマ**」の資格取得を目指している方
* IT企業やIT部門の教育研修部門において、新人研修やリスキルのためのオンライン教材をお探しの方

#### この記事を含むシリーズ全体像

この記事はJava SEの一部の機能・仕様を取り上げたものですが、一連のシリーズになっており、**シリーズ全体でJava SEを網羅**しています。また認定資格である「**Oracle認定Javaプログラマ**」（Silver、Gold）の範囲もカバーしています。シリーズの全体像および「Oracle認定Javaプログラマ」の範囲との対応関係については、以下を参照ください。

https://qiita.com/KenyaSaitoh/items/4711a078a851510bc4da

## 2.1 Javaプログラムの基本と"Hello, World!"

### チャプターの概要

このチャプターでは、テキストエディタを用いて最も基本的なJavaプログラム（"Hello, World!"）を作成し、動作させる方法を学びます。
そして作成した"Hello, World!"を題材にして、プログラムの基本構造を理解しましょう。

### 2.1.1 最初のJavaプログラム

#### Javaプログラム開発の流れ

既出のとおり、Javaプログラムを実行するためには、①まずJavaのソースコードを記述したソースファイル（.javaファイル）を作成します。
②次にソースファイルをコンパイルし、クラスファイル（.classファイル）を生成します。
③そしてコンパイルによって生成されたクラスファイルを、実行します。

【表2-1-1】Javaプログラム開発の流れ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/597954/86bac62f-aa64-d3d6-3fec-bac44147c3e3.png)

#### Hello, World!

それでは、最初のJavaプログラムを作成してみましょう。どのプログラミング言語でも、最初に動かすプログラムはHello Worldと相場が決まっていますので、本コースもそれに倣います。具体的には、画面すなわちコンソールに対して、 "Hello, World!"という短い文字列を出力するためのプログラムを作成します。
本コースでは次のチャプターからは統合開発環境であるEclipseを利用しますが、ここではJavaのコンパイルから実行に至る基本的な仕組みを理解するために、素のJDKとテキストエディタを使用してプログラムを作成します。JDKのインストール方法については、チャプター1.2を参照してください。
使用するテキストエディタは、Windowsの場合は「メモ帳」、macOSの場合は「テキストエディット」など、OSに標準で搭載されているもので問題ありませんが、ここではメモ帳を利用します。
ではメモ帳を立ち上げます。そして以下のように入力します。

```java:Hello.java
class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
```

コンソールに"Hello, World!"という文字列を出力するためだけに、5行ものコードを書かないといけないことに驚かれた方もいるかもしれません。Javaでは、詳細は後述しますが、どのようなプログラムであっても最低でも1つの「クラス」を作成し、クラス内に「mainメソッド」を記述する必要があるため、このようなコードになります。このコードの場合、クラス名はHelloとしました。
入力が終わりましたら保存します。ここではファイルの保存先は、チャプター1.2の環境も踏まえて"C:/LetsLearn/Java"ディレクトリ下の"learn_java_basic/02_hello/src"ディレクトリとします。

Javaでは、クラス名とファイル名（除く拡張子）は基本的に一致させる必要があります。従ってこのコードは、"Hello.java"という名前でファイルを保存してください。このようにJavaのソースファイルは、必ず拡張子が".java"になります。

:::note info
厳密には、1つのソースファイルに2つ以上のクラスを宣言することができます。ただし特別な理由がない限りは、管理しやすいという観点から「1ソースファイル＝1クラス」にすることを推奨します。本コースでもそのようにしています。
※ここではインナークラス（チャプター21.1参照）は論点の対象外
:::

### 2.1.2 コンパイルと実行

#### ソースファイルのコンパイル

それでは、先ほど保存したJavaのソースファイル"Hello.java"をコンパイルします。
コンパイルのためのコマンドを投入するために、ターミナルを立ち上げます。Windowsの場合はコマンドプロンプト、macOSの場合はターミナルを利用します。ターミナルを立ち上げたら、先ほどソースファイルを保存したディレクトリに移動します。
Javaのソースファイルをコンパイルするためには、JDKに付属するjavacコマンドを利用します。試しに、ターミナルにjavacと打ってエンターキーを押下してみてください。パスが正しく設定されていれば、以下のようにjavacコマンドの使用方法が表示されます。

```
$ javac
使用方法: javac <options> <source  files>
使用可能なオプションには次のものがあります。
  @<filename>                  ファイルからの読取りオプションおよびファイル名
  -Akey[=value]                注釈プロセッサに渡されるオプション
  --add-modules  <module>(,<module>)*
        初期モジュールに加えて解決するルート・モジュール、または<module>が
                ALL-MODULE-PATHである場合はモジュール・パスのすべてのモジュール。
....以下省略....
```

それではjavacコマンドで、ソースファイル"Hello.java"をコンパイルしてみましょう。
以下のように入力して、エンターキーを押下します。

```
javac Hello.java
```

ソースファイルの指定は、相対パスでも絶対パスでも構いません。仮にこのプログラムに記述ミスがあり、例えばダブルクオーテーションの「閉じ漏れ」があったとすると、以下のようにエラーメッセージが表示されてコンパイルは失敗します。

```
$ javac Hello.java
Hello.java:3: エラー: 文字列リテラルが閉じられていません
        System.out.println("Hello,  World!);
                           ^
エラー1個
```

コンパイルに成功すると、同じディレクトリに"Hello.class"というファイルが生成されます。このようにコンパイルによって生成されるファイルを、クラスファイルと呼びます。クラスファイルの拡張子は".class"になります。

#### クラスファイルの実行

次に、生成されたクラスファイルを実行します。
クラスファイルを実行するためには、JDKに付属するjavaコマンドを利用します。試しに、ターミナルにjavaと打ってエンターキーを押下してみてください。パスが正しく設定されていれば、以下のようにjavaコマンドの使用方法が表示されます。

```
$ java
使用方法: java [options]  <mainclass> [args...]
           (クラスを実行する場合)
   または  java [options] -jar  <jarfile> [args...]
           (jarファイルを実行する場合)
   または  java [options] -m  <module>[/<mainclass>] [args...]
       java [options] --module  <module>[/<mainclass>] [args...]
           (モジュールのメイン・クラスを実行する場合)
   または  java [options]  <sourcefile> [args]
           (単一のソースファイル・プログラムを実行する場合)
....以下省略....
```

それでは、javaコマンドでHelloクラスを実行してみましょう。以下のように入力して、エンターキーを押下します。

```
java Hello
```

このように入力すると、カレントディレクトリ（現在のディレクトリ）を起点に"Hello.class"ファイルが検索されます。そして1つのプロセスとしてJavaランタイムが立ち上がり、見つかったクラスファイルが実行されます。
javacコマンドによるコンパイルでは引数にソースファイルを指定しましたが、javaコマンドによる実行では、引数に指定するのはクラスファイル名（"Hello.class"）ではなく、クラス名（"Hello"）であるという点に注意が必要です。
実行に成功すると、コンソールに以下のように表示されます。

```
Hello, World!
```

#### クラスパス

javaコマンドを投入すると、指定されたクラス（先の例だとHelloクラス）を表すクラスファイル（先の例だとHello.classファイル）がファイルシステム内から検索され、実行されます。このときクラスファイルを検索するにあたり、起点となるパスをクラスパス[^1]と呼びます。ターミナルからjavaコマンドを投入する場合は、カレントディレクトがデフォルトのクラスパスになります。従ってHello.classファイルの配置場所で`java Hello`とコマンドを投入すると、対象クラスが見つかり実行されます。またjavaコマンドを投入するとき、-classpathオプションによりクラスパスを明示的に指定することも可能です。
本コースでは開発環境としてEclipseを使用するため、クラスパスを意識するケースは殆どありませんが、本コース以降にステップアップする場合は正しく理解する必要があるでしょう。

### 2.1.3 Javaプログラムの基本構造

ここでは、前項で作成したHello.javaを題材に、Javaプログラムの基本的な構造を説明します。

#### クラスとメソッド

Javaプログラムは、必ず「クラス」の中に記述します。
クラスとは手続きとデータをひとまとめにした概念で、オブジェクト指向型プログラミングにおけるプログラムの基本的な粒度です。クラスについては、チャプター7.1で詳しく取り上げます。
クラスはキーワードclassによって宣言し、`{`から`}`で表される範囲の中に処理を記述します。正しく`}`が閉じられていないと、コンパイル時にエラーが発生します。ここでは`class Hello`と宣言していますので、このコードはHelloクラスを作成するためのものになります。
クラスは任意の数のメンバーを保持することができます。メンバーとは、メソッドやフィールドなどのことを指します。フィールドとは、クラスが保持するデータすなわち属性のことであり、またメソッドとは、クラスが保持する手続きすなわち振る舞いのことですが、詳細はチャプター7.2で取り上げるため、ここではメソッドのみを簡単に触れる程度に留めます。
メソッドは基本的に、戻り値（ここではvoid型）、メソッド名（ここではmain）、引数（ここではString配列型）という構成で宣言します。メソッドもクラスと同様に`{`から`}`で表される範囲の中に処理を記述します。メソッドについても正しく`}`が閉じられていないと、コンパイル時にエラーが発生します。Helloクラスの場合は、メインメソッドを1つだけ保持しています。

#### メインメソッドと命令文

メインメソッドとは、Javaプログラム実行時に最初に呼び出されるメソッドです。メインメソッドは必ず`main`という名前を付け、`public static void main(String[] args)`と宣言する[^2]必要があります。またメインメソッドを持つクラスを、メインクラスと呼びます。1つのJavaプログラムは、必ず1つ以上のメインクラスから構成されます。
それではメインメソッドの中を見ていきましょう。メソッドの中には、処理の流れに従って命令を記述していきます。ここでは`System.out.println()`という命令を呼び出しています。これはコンソールに文字列を表示するためのAPIで、Java SEのクラスライブラリによって提供されている機能です。このAPI呼び出しにより"Hello, World!"という文字列がコンソールに表示され、最後に改行が行われます。

:::note warn
Javaでは、命令文の文末には必ずセミコロン`;`を記述する必要があります。
:::

:::note info
`System.out.println()`は、厳密には「Systemクラスのoutフィールドが表すPrintWriterオブジェクトの、println()というメソッド」という意味です。ここでは「コンソールに文字列を表示するためのAPI呼び出し」と理解しておけば十分でしょう。
:::

### 2.1.4 Javaソースコードの基本的な記法

#### ソースコードの基本的な記法

##### ブロック

ブロックとは、`{`から`}`で表される範囲のことです。メソッドや初期化子（後述）、if文、for文、try-catch文といったステートメントもブロックに該当します。ブロックは、正しく閉じられていないとコンパイル時にエラーが発生します。

##### 空白

Javaでは、クラス名やメソッド名といった「意味のある単語」を空白によって分断することはできませんが、それ以外であれば任意の位置に空白を入れることができます。通常はソースコードの見た目を分かりやすくするために、イコールやプラスといった演算子の前後や、引数を列挙する場合などに用いるカンマの後ろ、またはifやforといった、制御ステートメントの後ろなどに空白を入れます。

##### 改行とセミコロン

Javaでは前述したように、命令文の文末には必ず`;`を付与する必要があります。1つの命令文がセミコロンで終わった後、改行を入れずに続けて次の命令文を記述することも可能ですが、通常はソースコードの見た目を分かりやすくするために`;`の後ろで改行します。
また1つの命令文が長くなってしまった場合は、命令文の途中に改行を入れることが可能です。プログラミング言語には、言語ごとに様々なソースコード規約がありますが、Javaの場合は80文字、または120文字で改行するのが一般的です。改行は、クラス名やメソッド名といった「意味のある単語」が分断されることがなければ任意の位置に入れることができますが、`.`や演算子の直後で改行するケースが多いでしょう。

##### インデント
Hello.javaを見ると、2行目から4行目にかけて行の左側に余白がありますが、この余白のことをインデント（または字下げ）と呼びます。

```java:Hello.java
class Hello {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}
```

インデントは、ソースコードの見た目を分かりやすくするためのもので、プログラムの動作には影響を与えません。またインデントは、メソッドやステートメントといったブロックの深さに応じて、1単位分のインデントを入れます。このようにすることで、ブロックの深さが一目瞭然で把握できるようになります。なおこのように、ブロックの中にブロックを記述し、ブロックが入れ子構造になることを「ネストする」という言い方をします。
インデントは空白文字でもタブでも表現することができますが、Javaでは通常インデントの1単位は空白4文字によって表現します。既出のHelloクラスでは、メインメソッドを記述するときに1単位分のインデントを入れ、メインメソッド内の処理で2単位分のインデントを入れています。
また前述したように、1つの命令文が長くなってしまった場合は命令文の途中で改行しますが、その際には1単位分のインデントを追加するのが一般的です。

#### コメント
コメントとは、ソースコードの中に記述する「注釈」のことです。前述したようにソースコードは機械語にコンパイルされて実行されますが、コメントはコンパイル時に除外されるため、プログラムの動作には一切影響を与えません。
コメントの目的は、大きく2つあります。

##### コメントの目的(1)：処理の無効化
1つ目は、一度記述した命令文をコメント化し、一時的に処理を無効化させることです。このように命令文をコメント化することを、コメントアウトと呼びます。コメントアウトにより不必要になった処理を削除するのではなく、必要に応じて後から復活させることが可能になります。コメントアウトは、デバッグ（不具合の発生個所をソースコード上で特定する作業をデバッグと呼ぶ）をする上でも、有効な手法です。

##### コメントの目的(2)：可読性の向上
もう1つは、ソースコードの可読性を高めることです。
ソースコードは、特に比較的規模の大きなシステム開発では、第三者によって読まれる機会は少なくはありません。また作成者本人であっても、数日前に記述した内容を忘れてしまうケースも多々あるでしょう。従って読むだけで処理内容が分かるように、読みやすいコードを記述することはとても重要です。そして適切にコメントを追加すると、読みやすさを補完的に高めることができます。特に「なぜそういった設計になっているのか」といった「設計の意図」は、コードからだけでは読み取ることができないため適切なコメントが必要です。

#### Javaにおけるコメント

Javaでは、コメントは2通りの方法で記述します。
1つ目は単一行コメントです。`//`からその行の末尾（改行）までをコメントと見なします。

```java:【構文】単一行コメント
// 単一行コメント
```

行の先頭から記述しても、途中から記述しても問題ありません。
もう1つは複数行コメントです。`/*`から`*/`までのコード全体を、コメントと見なします。

```java:【構文】複数行コメント
/*
 複数行コメント
*/
```

### 2.1.5 識別子とキーワード

#### 識別子とは

Javaでは、クラス名、パッケージ名、メソッド名、フィールド名、および変数名のことを、識別子と呼びます。
識別子は以下のルールに則って命名します。命名ルールに違反するとコンパイルエラーになります。

•	使用できるのは、英数字、アンダースコア（_)、ドルマーク（$)と、日本語などのマルチバイト文字
•	数字を1文字目に使用することはできない
•	後述する予約語は、使用できない
•	大文字と小文字は区別される
•	文字数制限はない

#### 予約語

Javaには、以下の表にあるような予約語（キーワードとも呼ばれる）があります。これらは識別子に使用することができません。

【表2-1-1】Javaの予約語
||||||
|--|--|--|--|--|
|abstract|assert|boolean|break|byte|
|case|catch|char|class|const|
|continue|default|do|double|else|
|enum|extends|final|finally|float|
|for|goto|if|implements|import|
|instanceof|int|interface|long|native|
|new|package|private|protected|public|
|return|short|static|strictfp|super|
|switch|synchrnized|this|throw|throws|
|transient|try|void|volatile|while|
||||||

また予約語ではありませんが、true、false、nullといった特殊なリテラルも、識別子に使うことはできません。

### このチャプターで学んだこと

このチャプターでは、以下のことを学びました。

1. ソースファイルをコンパイルしてクラスファイルを生成するという、Javaプログラム開発の基本的な流れについて。
1. javacコマンドで、ソースファイルをコンパイルする手順について。
1. javaコマンドで、クラスファイルを実行する手順について。
1. クラスの基本的な構造や、メインメソッドについて。
1. ブロック、インデントなど、ソースコードの基本的な記法について。
1. コメントを記述する目的や、具体的な記述方法について。
1. Javaにおける識別子や予約語について。

[^1]:クラスを検索するときに起点となるパスは、厳密にはモジュールシステム（『Java Advanced編』参照）が導入されている場合はモジュールパス、そうでない場合はクラスパスになる。
[^2]:可変引数（チャプター7.3）を使って`public static void main(String... args)`とすることも可能。