6 単純なソース・ファイルおよびインスタンスのmainメソッド
単純なソース・ファイルおよびインスタンスのmain
メソッドを使用すると、受講者は大規模なプログラム用に設計されたすべての言語機能を理解しなくても、最初のプログラムを作成できます。
ノート:
これはプレビュー機能です。プレビュー機能は、設計、仕様および実装が完了したが、永続的でない機能です。プレビュー機能は、将来のJava SEリリースで、異なる形式で存在することもあれば、まったく存在しないこともあります。プレビュー機能が含まれているコードをコンパイルして実行するには、追加のコマンド行オプションを指定する必要があります。『Preview Language and VM Features』を参照してください。
単純なソース・ファイルおよびインスタンスのmain
メソッドの背景情報は、JEP 495を参照してください。
Javaプログラミング言語は、何年にもわたり大規模なチームによって開発および保守される、大規模で複雑なアプリケーションの開発に優れています。データの非表示、再利用、アクセス制御、ネームスペース管理、モジュール性のための豊富な機能を備えており、コンポーネントを個別に開発および保守しながらクリーンに構成できます。その大規模コンポーネントの構成は、大規模プログラミングと呼ばれます。
ただし、Javaプログラミング言語は最初の言語になることも意図しており、小規模プログラミング(コンポーネントの内部にあるすべてのもの)に役立つ多くの構文を提供しています。プログラマが最初に取りかかるとき、大規模なプログラムをチームで記述するのではなく、小規模なプログラムを自分で記述します。この段階では、クラス、パッケージおよびモジュールの大規模プログラミングの概念は必要ありません。
プログラミングを教える場合、講師はまず、変数、制御フローおよびサブルーチンの基本的な小規模プログラミングの概念から始めます。クラス、パッケージおよびモジュールの大規模プログラミングの概念は必要ありません。プログラミングを学習している受講者は、様々なユーザーが作成したコンポーネントを個別に進化させるのに後で役立つカプセル化とネームスペースは不要です。
main
メソッドは、小規模プログラミングに対するJavaプログラミング言語のサポートを次のように強化します:
static
ではなく、public
である必要がなく、String[]
パラメータを必要としないインスタンスのmain
メソッドを許可することで、Javaプログラムが起動されるプロトコルを強化します。「javaランチャおよびインスタンスのメイン・メソッドを使用した単純なソース・ファイルの実行」を参照してください。- 受講者および開発者が単純なソース・ファイルを作成できるようにします。これは、クラス宣言で囲まれていないフィールドおよびメソッドを含むソース・ファイルです。単純なソース・ファイルは、メンバーが囲まれていないフィールドおよびメソッドであるクラスを暗黙的に宣言します。Java言語仕様の8.1.8暗黙的に宣言されたクラスおよび「単純なソース・ファイルの作成」を参照してください。
- コンソールを使用した単純なテキストI/O用のメソッドと、java.baseモジュールによってエクスポートされたパッケージの最上位のpublicクラスおよびインタフェースを自動的にインポートします。「java.io.IOのstaticメソッドとモジュールjava.baseの自動インポート」を参照してください。
HelloWorld
プログラムについて考えてみます。
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
この最初のプログラムでは:
class
宣言および必須のpublic
アクセス修飾子は、大規模プログラミング構文です。外部コンポーネントへの明確に定義されたインタフェースを使用してコード・ユニットをカプセル化する場合に役立ちますが、この小さな例では意味がありません。- コードと外部コンポーネント(この場合はオペレーティング・システムのシェル)のインタフェースをとるための
String[] args
パラメータも存在します。特に、HelloWorld
のような単純なプログラムでは使用されないため、ここでは不可解で役に立ちません。 static
修飾子は、Javaのクラスとオブジェクト・モデルの一部です。初心者にとって、static
は不可解なだけでなく有害です。main
から呼び出して使用できるメソッドまたはフィールドをさらに追加するために、受講者はこれらすべてをstatic
として宣言するか(一般的な習慣でもよい習慣でもないイディオムを伝播します)、静的メンバーとインスタンス・メンバーの違いに直面し、オブジェクトをインスタンス化する方法について学習する必要があります。
単純なソース・ファイルおよびインスタンスのmain
メソッドは、プログラマがアクセス修飾子、static
修飾子またはString[]
パラメータを使用せずにプログラムを記述できるようにすることで、HelloWorld
などの単純なプログラムを記述する複雑さを軽減します。受講者は、独立した方言とはかけ離れたJava言語を使用して、単一クラス・プログラムの合理化された宣言を記述し、後で開始プログラムをシームレスに拡張して、スキルの成長に応じてより高度な機能を含めることができるようになりました。Javaの熟練者は、単純なソース・ファイルおよびインスタンスのmain
メソッドが、Java言語の大規模プログラミング・スキャフォールディングを必要としない単純なJavaプログラムを記述する際に便利な機能であることに気づく場合もあります。講師は、大規模プログラミング構文の紹介を、必要になるまで延期できます。
単純なソース・ファイルの作成
Java言語では、すべてのクラスがパッケージ内にあり、すべてのパッケージがモジュール内にあります。これらのネームスペースおよびカプセル化の構文は、すべてのコードに適用されます。ただし、それらを必要としない小さなプログラムでは省略できます。
クラス・ネームスペースを必要としないプログラムは、package
文を省略して、そのクラスを無名パッケージの暗黙的なメンバーにすることができます。無名パッケージ内のクラスは、名前付きパッケージのクラスから明示的に参照できません。パッケージをカプセル化する必要がないプログラムは、モジュール宣言を省略して、そのパッケージを無名モジュールの暗黙的なメンバーにすることができます。無名モジュール内のパッケージは、名前付きモジュール内のパッケージから明示的に参照できません。
クラスは、主要目的であるオブジェクトの構築用のテンプレートとして機能する前に、メソッドおよびフィールドの名前空間として機能します。次の場合に、クラスの概念に直面することを受講者に求めてはなりません。
- 変数、制御フローおよびサブルーチンの基本的な構成要素に慣れる前
- オブジェクト指向の学習を始める前
- まだ単純な単一ファイル・プログラムを作成している場合。
すべてのメソッドがクラスに存在する場合でも、必要のないコードの明示的なクラス宣言の要求を停止できます。これは、必要のないコードの明示的なパッケージ宣言やモジュール宣言は必要ないためです。
Javaコンパイラは、クラス宣言で囲まれていないメソッドを含むソース・ファイルを検出すると、そのメソッド、同様のメソッド、およびファイル内の囲まれていないフィールドとクラスを、暗黙的に宣言された最上位のクラスの本体を形成するものと見なします。暗黙的に宣言されたクラスを含むソース・ファイルは、単純なソース・ファイルと呼ばれます。
単純なソース・ファイルの暗黙的に宣言されたクラス:
- 無名パッケージの
final
最上位クラスです。 - java.lang.Objectを拡張し、インタフェースを実装しません。
- パラメータのないデフォルト・コンストラクタを持ち、他のコンストラクタはありません。
- メンバーとして、単純なソース・ファイルにフィールドとメソッドがあります。
- インスタンスの
main
メソッドである起動可能なmainメソッドが必要です。「javaランチャおよびインスタンスのメイン・メソッドを使用した単純なソース・ファイルの実行」を参照してください。
暗黙的に宣言されたクラスは名前で参照できないため、その静的メソッドへのメソッド参照はありません。ただし、this
キーワードは引き続き使用でき、インスタンス・メソッドへのメソッド参照も使用できます。
単純なソース・ファイルのコードは、暗黙的に宣言されたクラスを名前で参照できないため、暗黙的に宣言されたクラスのインスタンスは直接構築できません。このようなクラスは、スタンドアロン・プログラムとして、またはプログラムのエントリ・ポイントとしてのみ役立ちます。したがって、暗黙的に宣言されたクラスには、「javaランチャおよびインスタンスのメイン・メソッドを使用した単純なソース・ファイルの実行」の説明に従って起動できるmain
メソッドが必要です。この要件は、Javaコンパイラによって適用されます。
暗黙的に宣言されたクラスは無名パッケージに存在し、無名パッケージは無名モジュールに存在します。(複数のクラス・ローダーを除き)無名パッケージは1つしか存在できず、無名モジュールも1つしか存在できませんが、無名モジュールには暗黙的に宣言されたクラスが複数存在できます。暗黙的に宣言されるすべてのクラスは、main
メソッドを含み、プログラムを表します。したがって、無名パッケージ内の暗黙的に宣言された複数のクラスは、複数のプログラムを表します。
暗黙的に宣言されたクラスは、明示的に宣言されたクラスと類似しています。メンバーは同じ修飾子(private
やstatic
など)を持つことができ、修飾子のデフォルトは同じです(package
アクセスやインスタンス・メンバーシップなど)。1つの重要な違いは、暗黙的に宣言されたクラスにはデフォルトのゼロ・パラメータ・コンストラクタがあるものの、他のコンストラクタは持てないことです。
HelloWorld
プログラムを単純なソース・ファイルとして記述できるようになりました:void main() {
System.out.println("Hello, World!");
}
main
メソッド(インスタンスのmain
メソッドであるvoid main()
)があります。最上位のメンバーは暗黙的に宣言されたクラスのメンバーとして解釈されるため、プログラムは次のように記述することもできます:String greeting() { return "Hello, World!"; }
void main() {
System.out.println(greeting());
}
String greeting = "Hello, World!";
void main() {
System.out.println(greeting);
}
java
コマンドライン・ツールを使用して、HelloWorld.java
という名前の単純なソース・ファイルを次のように起動できます:java HelloWorld.java
Javaコンパイラは、そのファイルを起動可能なクラス・ファイルHelloWorld.class
にコンパイルします。この場合、コンパイラはクラス名にHelloWorld
を実装詳細として選択します。ただし、依然としてこの名前をJavaソース・コードで直接使用することはできません。「javaランチャおよびインスタンスのメイン・メソッドを使用した単純なソース・ファイルの実行」を参照してください。
この時点で、javadoc
ツールは暗黙的に宣言されたクラスのAPIドキュメントを生成できません。これは、暗黙的に宣言されたクラスが他のクラスからアクセス可能なAPIを定義していないためです。ただし、暗黙的に宣言されたクラスのフィールドおよびメソッドは、APIドキュメントを生成できます。
java.io.IOのstaticメソッドとモジュールjava.baseの自動インポート
すべての単純なソース・ファイルは、クラスjava.io.IO
の静的メソッドを自動的にインポートします:
- println(Object): 指定されたオブジェクトの文字列表現をシステム・コンソールに書き込み、そのコンソールをフラッシュします。
- print(Object): 指定されたオブジェクトの文字列表現をシステム・コンソールに書き込み、行を終了し、そのコンソールをフラッシュします。
- readln(String): printを呼び出す場合と同様にプロンプトを書き込み、システム・コンソールから1行のテキストを読み取ります。
これは、オンデマンド静的インポート宣言import java.io.IO.*
がすべての単純なソース・ファイルの先頭に出現する場合と同じです。
したがって、HelloWorld
プログラムを次のようにさらに簡略化できます:
String greeting = "Hello, World!";
void main() {
println(greeting);
}
また、すべての単純なソース・ファイルは、java.baseモジュールによってエクスポートされたすべてのパッケージに含まれる最上位のパブリック・クラスおよびインタフェースをすべてオンデマンドでインポートします。これは、モジュール・インポート宣言import module java.base
がすべての単純なソース・ファイルの最初に出現する場合と同じです。詳細は、「モジュール・インポート宣言」を参照してください。
次の例は、java.baseモジュールによってエクスポートされたパッケージに含まれているため、Map、Stream、CollectorsまたはFunctionのインポート宣言を必要としない単純なソース・ファイルです。
void main() {
String[] fruits = new String[] { "apple", "berry", "citrus" };
Map<String, String> m = Stream
.of(fruits)
.collect(Collectors.toMap(
s -> s.toUpperCase().substring(0,1),
Function.identity()));
m.forEach((k, v) -> println(k + " " + v));
}
javaランチャおよびインスタンスのメイン・メソッドを使用した単純なソース・ファイルの実行
java
ランチャを使用して、単純なソース・ファイルを含むJavaソース・コードの単一ファイルとして提供されるプログラムを実行できます。
たとえば、HelloWorld.java
が単純なソース・ファイルの場合は、次のコマンドで実行できます:
java HelloWorld.java
java
ランチャは、メモリー内の単純なソース・ファイルをコンパイルし、次のプロトコルで説明するように、main
メソッドを検索して起動します:
-
単純なソース・ファイルに
String[]
パラメータを持つmain
メソッドが含まれている場合、java
ランチャはそのメソッドを選択します。それ以外の場合、単純なソース・ファイルにパラメータのない
main
メソッドが含まれている場合、java
ランチャはそのメソッドを選択します。それ以外の場合、
java
ランチャはエラーをレポートして終了します。 -
java
ランチャがstatic main
メソッドを選択した場合、そのメソッドが起動されます。それ以外の場合、
java
ランチャはインスタンスのmain
メソッドを選択します。java
ランチャは、単純なソース・ファイルの暗黙的に宣言されたクラスのデフォルト・コンストラクタを起動します。次に、結果のオブジェクトのmainメソッドを呼び出します。
このプロトコルで起動できるmain
メソッドは、起動可能なメイン・メソッドと呼ばれます。たとえば、単純なソース・ファイルHelloWorld.java
を再度考えてみます:
void main() {
System.out.println("Hello, World!");
}
1つの起動可能なmain
メソッド(インスタンスのmain
メソッドであるvoid main()
)があります。
次の単純なソース・ファイルの例には、String[]
パラメータを持つインスタンスのmain
メソッドが含まれています:
void main(String[] args) {
System.out.println("Hello, " + args[0]);
}