Java'sHello

では、恒例の、Hello World から、始めましょう。
(どのプログラム言語であれ、これを表示するのが、恒例のようです)
Javaの場合、
この、HelloWorld.java 自体、複雑です。
まず、このプログラムが、コンソールに表示するのは、
	Hello, Java
だけです。
しかししかし、
 必ず、どんなコードも、
 class の中に、書かなければ、
いけません。
例えば、Python なら、
 print("Hello, Python")
これだけで、同じことができます。
これは、これで、素晴らしいのですが、、
私は、Javaは、細かいルールを、克服したとき、
正確に言えば、細かいルールが、
 一貫したルールであると、感じるようになったとき、
大きくて、複雑なプログラムを、書く場合、
より、ストレスレスで、書けるようになるのだと、信じています。

あと、気を付けるべきは、
 main()メソッド
  / public static void main(String[] args){ }
を、持つ、
 classの名前 を、必ず、ファイル名と、一致させなければ、
いけません。


では、上から順に、このコードを、チェックしていきます。

	class HelloWorld{
		・	・	・
	}
このくくりは、class/クラス の宣言です。
宣言というのは、堅苦しいですが、
要は、HelloWorld という、名前 の、class を、作りますよ。
という意味です。
ここでのポイントは、
 class という、キーワード と、
 「HelloWorld」 のように、プログラマが、決めた、
 特別な名前を、識別子/identifier と呼ぶ。
ということです。

では、次の行:
	public static void main(String[] ars){
		・	・	・
	}
これは、通常、簡単に、
	main()メソッド
と、呼ばれているもので、アプレット/Applet を除いては、
必ず、ここからプログラムがスタートします。
このコードを、今の段階で、完全に理解することは、
無理ですが、必ず、使うコードなので、
後から、完全に理解するためにも、おおざっぱに、理解しておきましょう。

まず、
	public
これは、
	アクセス修飾子
と、呼ばれるもので、この publicキーワード が、使われているときは、
このclassの、外から、「直接」アクセスできることを意味しています。
逆に、オブジェクト指向の、カプセル化の部分でも、少し触れましたが、
	privateキーワード
が使われているときは、外のクラスからは、「直接」アクセスできません。
ここで、main()メソッドが、publicでなければならないのは、
Javaプログラムの出発点として、このメソッドを、これを含むclassの、
外から、呼び出すからです。

次は、
	static
です。
この、static(不変の、静的な)があることによって、
HelloWordクラス の、オブジェクトを、 介さず、
呼ぶことができるわけです。
この、static という単語の意味からも、理解できますが、
このメソッドは、「不変」なのです。
class/クラス の、実際の例としてのオブジェクト とは、
関係ないのです。
ですから、この、main()メソッドは、
	直接、
	java
	というプログラム/アプリケーション
から、呼びだされて、実行されます。
ちなみに、~.javaファイル を、コンパイルするのは、
	javac
という、アプリケーションです。

では、
	void
です。
これは、メソッド(method) が、何の値も、返しませんよ、
と言っています。
多くのメソッドは、戻り値/返し値 を、返して、
その値を、変数 などに、保管する というような風にも、
使われたりしますが、
この main()メソッドは、何にも、返さないというわけです。

次は、
	main(String[] args)
についてです。
ここは、このメソッドの、核/ベース となる部分といってもいいでしょう。
このメソッド全体を、main()メソッド ともいうことからも分かります。
ここで、ちょっと気を付けるのは、Javaは、
	case-sensitive/大文字と小文字を違う文字として考える
なので、もし、Main()メソッドとして、宣言すると、main() とは、
違うメソッドになってしまうので、気を付けてください。

ここで、注目すべきは、
	(String[] args)
でしょうか。

まずは、その、
	()
の部分に注目してみます。
ここには、
	メソッド宣言時
には、
	パラメータ(変数)/parameter/仮引数(値ではない)
を書き、
この メソッド を使う段階では、
	引数/argument/実引数(値や、値を持った式・変数)
を、当てがいます/割り当てます。
もし、どんな引数も必要としない、メソッド を、宣言するときには、
	()/空のカッコ
を、書いてください。
これは、メソッドであるという目印として使われますので。

では、その中に書かれている
	String[] args
とは、何なのでしょうか?
これは、パラメータ変数 として、
	Stringオブジェクト の 配列
を、宣言し、それを、値 として、受け取ります/キャッチします と、
言っているのです。
Stringオブジェクトの配列???
と思われる読者の方もおられると思いますが、
先に申し上げましたように、今の段階では、このメソッドの、
完全理解は、難しいのです。
なんとなく、そんなもんかと思っていてください。
その他の部分でも、分からないところが、あると思いますが、
軽く、読んでおくだけでいいでしょう。
ただ、この、main()メソッドを暗記していないと、
プログラムを、作成できませんので、訳が分からなくとも、
そのことは、覚えておいてください。
また、暗記/または理解して覚える 時には、
その、覚えるべきに、「何度もあいさつする/helloと言う」
ことが、大事だと思われます。
いま、最初のあいさつをしたと思ってください。
(IDEを使えば、半自動で、書く方法があるようです)

さて、ここで、少しでも、経験のある方は、
特に、コマンドプロンプト/ターミナル で、Javaプログラムを実行
したことがある方は、いつも、
	java なになに(なになに.class の、なになに)
と書くだけで、
	java なになに "あ" "A" "う"
などのようには、実行していないぞ!
と思われる方も、多いでしょう。

わたしも、よくそのことに関しては、おかしいな、と思っているので、
今、ちょっとした、実験をしてみます。

	・・・
ここからは、まったく初心者の方は、負担が大きすぎると、
思われますので、軽く読み流すか、無視してください。
まず、
	String[] args
という引数を、実際に使うプログラムを書きます。

次に、
	まず、文字列2つを、プログラム実行の際に、与えて、
	実行
してみましょう。
(なんか、実験は、やや長くなりそうです。。)
まず、実際に、引数を、2つ与えて実行した場合、
こうなりました。
まあ、これに関しては、予想通りというか、
こうならなくては、困りますという感じですね。

では、次に、注目です!
しかし、どうしてこうなるのかは、説明できませんが、
今から、結論を言ってしまうのも、何ですが、
この main()メソッド に、関しては、
Javaのとりえとして、「文法の一貫性/ほぼ例外を認めないこと」
とは、反する、最終結論が出そうです。

前置きが長くなりましたが、
次の実験は、
	今のJavaプログラム
に、
	引数を、与えないで
実行してみることです。
結果は、こうなりました。

実行時エラー/例外(ArrayIndexOutOfBoundsException)
(コンパイルエラーと違って、ランタイム/実行時 に起きるエラー)
が、発生してしまいました。
この原因は、プログラムが、args[0] に、アクセスしようとした時に、
引数がないので、「どうなってんだい」 と、文句を言っている、、
ということです。

この結果に不満はないのですが、普通、私が見てきた
多くの例題プログラムでは、javaアプリケーション で、実行するとき、
引数を指定するということは、めったにありません。
それで、いつも、エラーは発生しません。

ただ、そもそも、メソッドに、引数が指定されている
	/ (String[] args)
のに、引数無しで、プログラムをスタートさせていいのか?
ということが疑問なのです。
ふつうは、それは許されないはずです。
では、普通は、それが許されないことを、確認するために、
こんなプログラムで、実験してみました。

まずは、エラーが発生しないパターンです。
まあ、当然の結果ですね。

では、次の結果が、問題です。
というより、コンパイルエラーになってしまうのですが。。。
では、コードを書き換えます。
	/ 本当は、リアルタイムで、実行したいのですが、
	/ やり方を、忘れてしまいました。
	/ いずれ、そのことも学習しますが、
	/ とりあえずは、今一つアンクールなやり方で我慢しましょう。
	/ よく考えたら、それには、Swingを使わないと、だめだった!
		/ まあ、いずれ、それも、学習する予定です。
では、まず先ほどのコードを、コメントアウト して、
	/ コメントアウト:
		/ コメントにして、実行できなくすること
		/ 反対語は、uncomment(アンコメント)
	returnStrArg(String[] argarg)メソッドに、
	引数を与えないで、
実行してみようと思います。
こんなコードになります。

まず、これは、Eclipse の画面なのですが、
	19行目に「✖」があります。
すでに、エラーなのですが、
試しにコンパイルしてみましょう。
すると、こうなりました。

ただ、自分のパソコンは、Window10・英語バージョンなので、
説明も英語です。
(ちょっとこれは言っておいたほうがいいので、
 言っておきますが、私のパソコンは、
 	cpu:インテルi7(ただしランクは下だと思う)
 	メモリ:32GBに増設(やりすぎかも?)
 です、、ですので、Eclipseの動作に、ストレスを感じませんが、
 ストレスを感じるのであれば、
 Eclipse が、どこに、ソースファイルを、
 おいているのかを調べ、そのファイルを、テキストエディタで、
 開くと、自分の使いなれた、エディタを使えます。
 私の使っている、ver4.6.3 では、
 右クリックから、「次で開く」という項目があり、
 そこから設定できます。
 詳細は、自分で調べてください。
 わたしも、簡単なコードは、テキストエディタで書いています。)
 
では、話を元に戻しましょう。
これを、Eclipseで、無理やり実行するとどうなるか?
こんなメッセージを、コンソールに返しました。

	Exception in thread "main" java.lang.Error: 		
	Unresolved compilation problem: 
	型 ParameterTest のメソッド returnStrArg(String[])
	は引数 () に適用できません

	at 	
	ParameterTestDrive.main
	(ParameterTestDrive.java:19)

まあ、これも、ご存知の方にとっては、当然の結末だと
思われるでしょうが、私がおかしいと思うのは、
	main()は、パラメータ変数args が、
	引数 を、要求しているのに、
	普通は、渡さずに実行している!
ということです。
今の結果を考えるならば、それは、おかしいはずです。

ですから、これは、
	実は、例外的なアクション
だと思われます。
まあ、これは、そもそも、状況も、いつもと違うので、
そういうことになるのでしょう。
この点に関しては、そういうものだと思っておけば、問題ないでしょう。

あと、このエラーに関して、Eclipse は、いくつかの解決案を、
提案してくれます。
	1. 例えば、引数に、barg を、入れてみたら?
	2. そもそもの、returnStrArg(String[] argarg)
	  を、returnStrArg() に変えてみたら?
	3. または、returnStrArg() を作ってみたら?
	  (オーバーロードする)
あと2つ提案していますが、それは、よくわかりませんでしたが、
ちょっと感動しました。
	・・・

では、次に進みましょう。
次も、難しいです。
	System.out.println("文字列/Stringオブジェクト");
というか、これに関して、完璧に説明されているのは、
見たことがありません!

まあ、一般的な説明では、
1.
Systemクラス という、Java が、
最初から用意しているクラスがあります。
	public final class System extends Object{
		・	・	・
	}

2.
そして、Systemクラスには、
	static PrintStream out;
が、定義されています。

3.
つまりこういうことですね。
	public final class System extends Object{
		・	・	・
		static PrintStream out;
		・	・	・		
	}

4.
そして、PrintStreamクラス には、
こんなメソッドがあります。
	void println();
	void println(いろいろなパラメータ);
		/ つまり、println()メソッドは、オバーロードされている.

5.
つまり、
	System.out.println(xx yyyy);
とすれば、
	PrintStreamオブジェクト.println(xx yyyy);
と同じなのだ。。

という説明です。

まあ、私も、最初は、この説明で、満足していましたが、
よく考えると、謎だらけです。

①
だったら、
	PrintStream.out.println(xx yyyy);
で、いいではないか?
これに関しては、少し、深く、学習すれば、解決するようです。

②
しかし、out とあるが、それはいつ、
インスタンス化/オブジェクト化
されるのだ?

③
しかも、簡略して書くと、
	class System{
			・	・	・
		PrintStream out = null;
			/ null … 何も参照していない。。
			/ 正確には、null と、等価のようです.
			・	・	・
	}
だそうである。
null だからと言って、なるほど なんて言ってられません。
何にも参照していないのです。

いろいろ調べたのですが、
	JVM / JavaVirtualMachine
の話が出てきました。
また、ほかのページでは、書いていることが、
理解できませんでしたが、かなり、深くまで、迫っているようです。
しかし、最後に、
	native修飾子
に、突き当ったようです。
(Java言語の知識だけでは、解決できないということ)
しかし、ということは、理解できるかはともかく、
正当な理屈はあるということですね。当たり前ですが。

もう私は、
	コンソールに出力する =
		System.out.println(xx yyyy);
を、暗記してくださいとしか言えません!

「xx yyyy」というのは、
引数無し(改行をする)とか、いろいろな引数に対応できるように、
オーバーロード されているので、簡略化して書きました。
オーバーロードに関しては、この先、記事を書く予定です。

普通は、ここまで、言及すると、
嫌気がさされそうなので、しないのが普通ですが、
私は、なるべく、深く、深く、アプローチしていくつもりです。
その方が、結局は、応用力がつくと思いますから。

結論:
	HelloWorld.java
	を、暗記しましょう!

無責任なようですが、
どの入門書でも、これに近いと思います。
明言していないだけです。
だって、out を、説明できる人は、限られていますから。
でも、これだけは、暗記していないと、先に進めません。

また、ほかの言語であっても、分からないのは、同じことです。
例えば、Python の、
	print("Hello, Python")
にしても、これが例えば、C言語で作られているとして、
そのソースコードを理解できる人がどれだけいるでしょうか?

print("Hello, Python")
と、
HelloWorld.java のソースコード
を、等価 と、考えるのは、
きついかもしれませんが、
その努力は、報われると信じるしかないでしょう。

結局、Javaを覚えるかどうかは、
Javaに魅力があるかどうかだと思います。

まあ、私が思う、Javaのいいところは、
1. いまだに、人気No.1。
	/ この意味は、トップレベルの人気という意味です。
2. 人気があれば、学習できるソースコードや、
  学ぶための本が多い!
3. 文法の細かさは、それを理解したとき、
  きっと、payできる。
4. 今や、場合によっては、Cよりも速い!

こんなところで、このチャプターは、終わりたいと思います。

私の書く、記事で、全て理解はできないかもしれませんが、
ほかの情報と合わせて、少しでも、お役に立てればと思います。

わたしも、Java(さん)には、頑張っていただきたいので、
少しでも、Javaファンが増えるように頑張ります。