【Java11】javacでコンパイルせずにJavaを実行してみた

#はじめに
本投稿はJava Advent Calendar 2018 の25日目の記事です。
初心者ではありますが、「参加することに意義がある！」の精神で、とりあえず空いていた枠に登録してしまいました。

最終日にも関わらず、薄い内容で申し訳ない気持ちもありますが初心者らしく、いざHelloWorld!

　※2018/12/26更新：サ〇タ業務の都合上、書きかけで投稿してしまったため、一部内容を追加。

#コンパイルせずにjavaを実行！？
Java11から、javacでコンパイルせずにjavaを実行できるという噂を聞きつけたため、HelloWorldしてみる。
ただし、ソースファイルが１つで完結する場合に限るなどの制限があるようなので、その辺も試してみる。

#環境
OS：Windows 10
Java：Oracle Open JDK 11
コンソール：コマンドプロンプト

#まずは普通のHelloWorldのみ
HelloJDK11.java

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

実行してみる

```
>java HelloJDK11.java
HelloWorld!
```
####めでたく、コンパイルせずに実行できました。
HelloJDK11.javaが存在するディレクトリには、HelloJDK11.classは作成されていませんでした。

#試しにjavacでコンパイルしてみる
```
>javac HelloJDK11.java

>java HelloJDK11
HelloWorld!
```
いつも通り、HelloJDK11.classが作成されました。
####しかし、、、

```
>java HelloJDK11.java
エラー: アプリケーション・クラス・パスにクラスが見つかりました: HelloJDK11
```
どうやら、クラスパス上にclassファイルが存在する場合、javaファイルをjavaコマンドで実行するとエラーとなるようです。
classファイルを削除すると、元通りjava HelloJDK11.javaで実行可能になりました。

#念のためにメソッド呼び出しをする
```
public class HelloJDK11 {

    public static void main(String[] args) {
        System.out.println("HelloWorld!");
        callMethod();
    }

    private static void callMethod() {
        System.out.println("CalledMethod!");
    }
}
```

実行

```
>java HelloJDK11.java
HelloWorld!
CalledMethod!
```
メソッド呼び出しも問題ありませんでした。
　※先ほど作成されていたclassファイルは削除しています。

#javaファイル名とクラス名を別名にする
HelloJDK11.java

```
public class SorryJDK11 {

    public static void main(String[] args) {

～先ほどと同様なので略～

}
```
javaファイル名：HelloJDK11.java
クラス名：SorryJDK11

実行とコンパイル

```
>java HelloJDK11.java
HelloWorld!
CalledMethod!

>javac HelloJDK11.java
HelloJDK11.java:1: エラー: クラス SorryJDK11はpublicであり、ファイルSorryJDK11.javaで宣言する必要があります
public class SorryJDK11 {
       ^
エラー1個
```
javaファイル名とクラス名が不一致だと、
#####コンパイル出来ないが、javaファイルのまま実行可能なようです。

#Personクラスを書いてnewしてみる
HelloJDK11.java

```
public class HelloJDK11 {
    public static void main(String[] args) {
        Person suzuki = new Person("鈴木");
        System.out.println(suzuki.getName());
    }
}

class Person {
    // フィールド
    private String name;
    // コンストラクタ
    public Person(String name) {
        this.name = name;
    }
    // ゲッター
    public String getName() {
        return this.name;
    }
}
```
実行

```
> java HelloJDK11.java
鈴木
```
問題ありませんでした。

#Personクラスを別ファイルに分割する
先ほどのHelloJDK11.javaをHelloJDK11.javaとPerson.javaの２ファイルに分割

```
>java HelloJDK11.java
HelloJDK11.java:7: エラー: シンボルを見つけられません
                Person suzuki = new Person("鈴木");
                ^
  シンボル:   クラス Person
  場所: クラス HelloJDK11
HelloJDK11.java:7: エラー: シンボルを見つけられません
                Person suzuki = new Person("鈴木");
                                    ^
  シンボル:   クラス Person
  場所: クラス HelloJDK11
エラー2個
エラー: コンパイルが失敗しました
```
コンパイルエラーが発生しました！
###冒頭でも記述した制限事項
「１つのソースファイルで完結している必要がある。」による
コンパイルエラーが発生しました。


#####一応、javacでコンパイルすると、

```
>javac HelloJDK11.java

```
HelloJDK11.classとPerson.classの２ファイルが作成され、javaコマンドで実行も出来ました。

#まとめ
新人研修の頃、毎回javacしてjavaしてたのが面倒だった記憶があるため、今回のJava11でのjavacなしで実行できるという動作に興味を持ち記事にしてみました。

[JEP 330](http://openjdk.java.net/jeps/330)によると、別にJavaをスクリプト言語のようにコンパイルなしで実行できるようにすることが目的ではないようです。

シェバン（shellの1行目の#!/bin/shとか）としてJavaファイルをコマンド実行することが目的とのこと。
./HelloJDK11
みたいに実行できるらしいです。（今度試してみます。）