Javaでパッケージにしたクラスのコンパイルと実行方法

任意のパッケージにあるクラスのコンパイルと実行方法についてです。環境はLinuxです。

ソースファイル(Main.java)


package sample01;

class Main {

	public static void main( String[] args ) {
	
		Number num = new Number();
		System.out.println( "Number is " + num.getNum() + "." );

	}
}

ソースファイル(Number.java)


package sample01;

public class Number {

	private int num;

	public Number() {
		num = 10;
	}

	public int getNum() {
		return num;
	}
}

MainクラスとNumberクラスはsample01というパッケージに属しています。

これらのソースを配置するのですが、ディレクトリ構成は以下のようにします。Javaフォルダは任意の場所に配置してください。

Javaフォルダにsrcフォルダとclassesフォルダを用意します。srcフォルダにsample01フォルダを作成し Main.java と Number.java を格納します。

コンパイルするためにコンパイル用のシェルを作成します。シェル名は compile.sh とします。compile.sh をsrcフォルダに格納します。実行権限もつけてください。

compile.shの内容


#!/bin/bash
javac -d ../classes -sourcepath ./ $1

compile.sh はカレントディレクトリでの実行とします。javacコマンドの説明をしておくと「-d . ./classes」はクラスファイルの出力先の指定、「-sourcepath ./」はソースファイルの検索場所となります。「$1」は compile.sh の引数です。

srcフォルダで compile.sh を実行します。引数は sample01/Main.java となります。

$ cd ./Java/src
$ ./compile.sh sample01/Main.java

compile.sh を実行すると /Java/classes/sample01 フォルダに Main.class と Number.class が生成されます。

Main.class を実行するにはclassesフォルダでjavaコマンドを実行します。引数は sample01.Main となります。

$ cd ./Java/classes
$ java sample01.Main

「Number is 10.」と表示されれば実行できています。

Javaのmainメソッドを public static void にしなかったらどうなるかやってみた。

Javaのmainメソッドを記載するとき、public static void main( String[ ] args ) { . . . と記載しますが、mainメソッドにpublicやstaticがなかったり、戻り値がvoid型でなかった場合にどうなるか?をやってみました。

Javaの実行環境はLinuxで、バージョンはJava8です。

サンプルソースです。


package sample08;

public class MainSample {

	public static void main( String[] args ) {

		System.out.println("Hello.");

	}
}

これを実行すると、画面に「Hello.」と表示されます。

mainメソッドのpublicを外してみました。
public static void main ⇒ static void main にしました。


package sample08;

public class MainSample {

	static void main( String[] args ) {

		System.out.println("Hello.");

	}
}

結果は、コンパイルはできましたが実行はできませんでした。

実行時の出力です。


$ java sample08.MainSample 
エラー: メイン・メソッドがクラスsample08.MainSampleで見つかりません。次のようにメイン・メソッドを定義してください。
   public static void main(String[] args)
またはJavaFXアプリケーション・クラスはjavafx.application.Applicationを拡張する必要があります

mainメソッドのアクセス修飾子にはpublicが必要とのこと。

mainメソッドのstaticを外してみました。
public static void main ⇒ public void main にしました。


package sample08;

public class MainSample {

	public void main( String[] args ) {

		System.out.println("Hello.");

	}
}

結果は、コンパイルはできましたが実行はできませんでした。

実行時の出力です。


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

mainメソッドにはstatic句の指定が必須のようです。

MainSampleクラス(mainメソッドがあるクラス)のインスタンスを生成するクラスがないから、インスタンスの生成なしで外部からmainメソッドを呼べるようにstaticである必要があるのでしょう。また外部から呼べるようにpublicとする必要があるのかと思いました。

クラスのアクセス修飾子であるpublicを外してみました。
public class MainSample ⇒ class MainSample にしました。


package sample08;

class MainSample {

	public static void main( String[] args ) {

		System.out.println("Hello.");

	}
}

結果は、コンパイルできて実行もできました。mainメソッドがあるクラスのアクセス修飾子は無指定でも良いようです。

クラスのアクセス修飾子が無指定でも実行できたということは、mainメソッドを呼ぶ人(おそらくJavaのVM)はどのパッケージにあるクラスでもアクセスできるということかと思います。

戻り値のvoidもintに変更してみました。
public static void main ⇒ public static int main にしました。


package sample08;

public class MainSample {

	public static int main( String[] args ) {

		System.out.println("Hello.");
		return 1;

	}
}

結果は、コンパイルはできましたが実行はできませんでした。

実行時の出力です。


$ java sample08.MainSample 
エラー: メイン・メソッドはクラスsample08.MainSampleのvoid型の値を返す必要があります。
次のようにメイン・メソッドを定義してください。
   public static void main(String[] args)

mainメソッドの戻り値はvoid型でないとダメなようです。なぜvoid以外の戻り値を許可していないのかは不明です。

でもそうするとJavaの結果は呼び出し元に返せないのかと思ってしまうのですが、戻り値を返すメソッドがありました。

System.exit()を記載すれば、呼び出し元にリターンコードを返せるようです。以下のようにします。


package sample08;

public class MainSample {

	public static void main( String[] args ) {

		System.out.println("Hello.");
		System.exit(255);
		
	}
}

このようにすると呼び出し元に255のリターンコードが返されます。

$ java sample08.MainSample
Hello.
$ echo $?
255

mainメソッドの引数ですが、String[] args となっています。これはmainメソッドの仕様でしょう。試しに String[] args ⇒ String args としたところ実行時にエラーとなりました。

ということで、Javaのmainメソッドは、

public static void main( String[ ] args ) { . . .

とするしかないようです。mainメソッドのあるクラスのアクセス修飾子はpublicがなくても大丈夫です。