【Java初心者向け】Javaのmainメソッドは「おまじない」として覚えてよいのか問題について

#はじめに
IT業界の経験は10年以上あるものの、ずっとメインフレームコンピュータなどのレガシーな環境でCOBOLの開発をやってきて、最近はCOBOLすら書いていなくて完全にエクセルで資料作ってる人がこの記事を書いております。Java初心者が記事を書いておりますので間違いなどありましたら指摘頂けると幸いです。

#この記事は何か
これまで個人開発でPythonを書いてきましたが、ふとOOPについて学んでみたくなったので、Javaを学んでみることにしました。まずは環境構築してHello Worldしてみたのですが、「mainメソッドはおまじない」という入門記事があったりして、本当にそれでいいのか？と気になって先に進めなくなり色々調べてみたという話です。

#とりあえず環境構築してHello Worldまでやってみる

###JDKのインストール
まずはJDK(Java Development Kit)をインストールするために[JDKのダウンロードページ](https://www.oracle.com/java/technologies/downloads/)にいきます。
2022年1月時点の最新バージョン(Java SE Development Kit 17.0.1)をダウンロードしてインストールします。バージョンを確認します。

```
$java --version
java 17.0.1 2021-10-19 LTS
Java(TM) SE Runtime Environment (build 17.0.1+12-LTS-39)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.1+12-LTS-39, mixed mode, sharing)
```
###VScodeにJavaのエクステンションをインストール
他の言語を書くのもVScodeを使っているのでエディタはVScodeを使います。VScodeのエクステンションでJavaを検索してJava Extention Packをインストールします。

![vscode-java.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256640/762d7bff-f872-de5f-0e06-53f8301dae59.png)

###Hello Worldやってみる
VScodeでHello Worldしてみます。

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

```
$ javac HelloWold.java
$ java HelloWorld
Hello World!!
```
Hello Worldできました!

#Hello Worldできましたで終われない...
とりあえず写経して書いてみましたが、

```
public static void main(String[] args)
```

この1文はなんでしょうか。
Javaの入門書にもこれはおまじないで...とか書かれていたりしますが、下記の記事に分かりやすく書かれていました。

[Javaの実行に欠かせないmainメソッド、その仕組みからしっかり解説](https://www.bold.ne.jp/engineer-club/java-main)

####mainメソッドの条件は以下全てを満たしているもの

>アクセス修飾子はpublicである
staticメソッドである
メソッドの戻り値はvoidである
メソッド名は“main”である(すべて小文字)
メソッドの引数は、Stringの配列(あるいはStringの可変長引数)”のみ“である ※引数の変数名は何でもよい

とりあえず自分でも動かして確認してみます。

####1)アクセス修飾子はpublicである
まず最初の単語はpublic以外不可ということなので以下の疑問を試してみました。

**疑問その1**
publicを削除したらダメなのか？

```
static void main(String[] args)
```
**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | ○        | エラー         |

**エラーメッセージ**

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

**疑問その2**
他のアクセス修飾子(例えばprivate)ではダメなのか？

```
private static void main(String[] args)
```
**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | ○        | エラー         |

**エラーメッセージ**

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

####2)staticメソッドである
static以外何があるのか良く理解していないのですが、これも削除したらどうなるかを試してみます。

**疑問**
staticを削除したらダメなのか？

```
public void main(String[] args)
```
**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | ○        | エラー         |

**エラーメッセージ**

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

####3)メソッドの戻り値はvoidである
メソッドの戻り値の型はvoidが指定されていますが、これを別の型にしてみるとどうなるかを試してみます。

**疑問**
voidを別の型に変更したらダメなのか？

```
public static int main(String[] args)
```
**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | エラー        | ー         |

**エラーメッセージ**

```
HelloWorld.java:4: エラー: return文が指定されていません
    }
    ^
エラー1個
```
####4)メソッド名は“main”である(すべて小文字)
メソッド名には"main"が指定されていますが、これを他のメソッド名にして試してみます。

**疑問**
メソッド名は“main”ではなく"hoge"に変更したらダメなのか？

```
public static void hoge(String[] args)
```
**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | ○        | エラー         |

**エラーメッセージ**

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

“main”ではなく"Main"と最初を大文字にしてもエラーなるようです。

####5)メソッドの引数は、Stringの配列(あるいはStringの可変長引数)”のみ“である ※引数の変数名は何でもよい
Stringは配列でなければならないが、引数の名前は変えられるそうです。

**疑問その1**
"String[]"を“String”に変更したらダメなのか？

```
public static void main(String args)
```
**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | ○        | エラー         |

**エラーメッセージ**

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

**疑問その2**
"args"を“hoge”に変更したらダメなのか？

```
public static void main(String[] hoge)
```

**結果**

|  | コンパイル | 実行 |
|:-----------|:------------:|:------------:|
| 結果      | ○        | ○         |

これは通りました。引数の名前はargsである必要はないのは知りませんでした。

#Stackoverflowは何と言ってるか
stackoverflowでも調べてみました。

[Why is the Java main method static?](https://stackoverflow.com/questions/146576/why-is-the-java-main-method-static)

>This is just convention. In fact, even the name main(), and the arguments passed in are purely convention.
(DeepL翻訳)
これは単なる慣習です。実際 main()という名前も 渡される引数も 純粋に慣例です。
When you run java.exe (or javaw.exe on Windows), what is really happening is a couple of Java Native Interface (JNI) calls. These calls load the DLL that is really the JVM (that's right - java.exe is NOT the JVM). JNI is the tool that we use when we have to bridge the virtual machine world, and the world of C, C++, etc... The reverse is also true - it is not possible (at least to my knowledge) to actually get a JVM running without using JNI.
(DeepL翻訳)
java.exe（Windowsではjavaw.exe）を実行するとき、実際に起こっているのは2つのJava Native Interface（JNI）呼び出しです。これらの呼び出しは、実際にJVMであるDLLをロードします（その通りです - java.exeはJVMではありません）。JNIは、仮想マシンの世界とCやC++などの世界との橋渡しをしなければならないときに使うツールです。逆もまた真なりで、JNIを使わずにJVMを実際に走らせることは（少なくとも私の知る限り）不可能なのです。(中略)
So, long and short: the reason it is static is b/c that's convenient. The reason it's called 'main' is that it had to be something, and main() is what they did in the old days of C (and in those days, the name of the function was important). I suppose that java.exe could have allowed you to just specify a fully qualified main method name, instead of just the class (java com.mycompany.Foo.someSpecialMain) - but that just makes it harder on IDEs to auto-detect the 'launchable' classes in a project.
(DeepL翻訳)
要するに、staticであるのは便利だからです。main'と呼ばれているのは、それが何かでなければならないからで、main()は昔のCの時代にはそうしていました（そしてその時代には関数の名前が重要だったのです）。java.exeでは、クラス名（java com.mycompany.Foo.someSpecialMain）だけでなく、完全修飾したメインメソッド名を指定できたのでしょうが、それではIDEがプロジェクト内の「起動可能」クラスを自動検出しにくくなるばかりです。

色々と理由があるもののconvention（慣習）であるということですね。（要約しすぎ。。）

#結論
おまじないとして覚えるのが良さそう。。

ただ変えても動く部分と変えたら動かなくなる部分があるというのは勉強になりました。

###Javaインストールの参考
まずは下記のYouTube（英語）でゼロから学んでいこうと思います。
[Java Tutorial for Beginners 2020](https://www.youtube.com/watch?v=eIrMbAQSU34&t=264s)

Macでvisual studio codeでJavaの環境を作る方法は下記を参照しました。
[How to Run Java in Visual Studio Code on Mac OS 2020](https://www.youtube.com/watch?v=hEJp98x_MPQ)