Javaによるプログラミングに関する世界観(G.戯言)です。Javaの世界観1(言語)も参照のこと。
オブジェクト指向と言う考え方を活かして、大規模な開発に使われることが多い。
一度書けばどこでも動く、と言う特徴を活かして、クロスプラットフォームアプリケーションの開発や、携帯デバイスでの開発に使われることが多い。
サーバー、エンタープライズ、メインフレームの開発に良く使われる。
旧来COBOLが使われていた事務処理用の開発でも良く使われる。
Javaは、ネイティブにコンパイルするのではなく、仮想マシンで動く言語です。
仮想マシンでは、中間コードにコンパイルし、Just-In-Time(JIT)コンパイルと最適化を行います。またガーベッジ・コレクションによって、メモリを自動的に管理し、要らなくなったメモリを自動で廃棄してくれます。そして、さまざまな分野(デスクトップ、エンタープライズからモバイルまで)でクロスプラットフォーム性を発揮し、"Write once, run anywhere"というスローガンの下、一度書いたアプリケーションがどこでも動く、という長所をうたっています。特に、Pure JavaのGUIライブラリであるSwingを使って作られたアプリケーションは、どのOSでも動きます。モバイルの分野でも、デスクトップでモバイルアプリケーションを開発することが出来ます。
Javaは、コンパイラ式の言語でも、インタプリタ式の言語でもありません。一度、コードをバイトコードと呼ばれる中間言語にコンパイルして、それを仮想マシンで実行します。C言語では、ソースコードを機械語にコンパイルしますが、さまざまなCPUのアーキテクチャが存在するため、別のCPUで動かそうと思った時はコンパイルし直したり、CPU依存のコードがあれば書き直さなければなりません。Javaでは、コードを一度バイトコードと呼ばれる「全てのCPUに共通のコード」にコンパイルし、実行時にそれぞれのCPUの機械語に変換します。これによって、「全てのプラットフォームで同じコードを動かす」ことが出来ます。逆に、速度や性能は犠牲になります。
また、Javaは共通のクラスライブラリを持っているほか、OSやプラットフォームに依存するAPIの部分を仮想マシンが吸収してくれます。これによって、あらゆるプラットフォームで共通のAPIが動き、別のプラットフォームのコードを同じものとして扱えます。たとえばモバイルのJavaコードをWindowsのJava上で開発できます。
もちろん、C/C++にクロスプラットフォーム性がないわけではありません。CPUに依存する内容がなければ、同じコードをさまざまな環境に向けて「クロスコンパイル」することができます。ですが、プラットフォームについてJavaのように共通のものとして扱うことはできません。たとえば、GTK+やQtのLinuxアプリケーションをWindowsで開発することは容易ではありません。アプリケーションのクロスプラットフォーム性が欲しいなら、WindowsでもQtを使わなければならなくなるでしょう。Javaではこうした問題はありません。普通にWindowsのJava向けに書いたコードが、そのままLinuxのJavaで動きます。
欠点としては、OSネイティブのアプリケーションとは、見た目もコードも違ったものになることです。JavaのSwingで書いたアプリケーションは、OSネイティブのアプリケーションとは見た目が違ってしまいます。そういう場合は、Javaと同様のシステムを持つ、Windowsの.NET Frameworkが使えます。C#/VB.NETで書かれたコードは、OSネイティブのものと同じルック・フィールを持ちます。
Javaはサーバーやエンタープライズの分野でも強いです。たとえば、Java EEのプラットフォームを使うことで、サーブレット向けのコードを書くことができます。これはPerl/CGIやPHPと同様の、サーバーサイドの技術です。特にJSPを用いれば、PHPと全く同じようなコードを書くことが出来ます。サーバーサイドのJavaは、Java VMこそオープンソースではありませんが、Apache Tomcatなど、オープンソース系の技術が多いことで知られています。そして、IBMのWebSphereのような、IBMのメインフレームコンピュータでも、Java EEは稼働します。Javaはとても汎用性のあるプラットフォームで、Windows、UNIX、Linux、モバイル、そしてIBMのメインフレームでも動きます。
Javaの文法的な側面を見ると、「完全なオブジェクト指向言語」であると言えます。オブジェクト指向はダイナブック構想で知られるアラン・ケイのSmalltalkで生まれた考え方で、プログラムをオブジェクト(もの)の形式で書き、プログラムのアルゴリズムとデータ構造を「クラス」で設計した後に、まるでものを作ったり破棄したり操作したりするかのようにプログラムを書くことができます。これにより、以下のようなコードが成り立ちます。
HogeObject.java
public class HogeObject { private int size; public void change(int x) { this.size = x; } public void print() { System.out.println(this.size); } }
Main.java
public class Main { public static void main(String[] args) { HogeObject hobj = new HogeObject(); hobj.change(2); hobj.print(); hobj.change(10); hobj.print(); } }
このように、まるで「もの」であるかのようにプログラムコードを扱うことができます。これがJavaの最大の特徴です。このようにすることによって、プログラム間のデータの共有を容易にし、またプログラムの再利用を促進することができます。(たとえば、メンバ変数はどのメンバ関数からもアクセスできる。このようにすることで、オブジェクトのインスタンスとメソッドを容易に関連づけられる。)継承による機能を追加した拡張クラスの作成や、プログラムに共通のインターフェースの実装のような機能を使うことで、一度書いたプログラムのコードを再利用することが容易となり、大規模なプログラム開発を可能にしてくれます。
ある意味、Javaは「コードとデータの再利用」をとても大切にした言語だと言えるでしょう。
後日注記:要するに、オブジェクト指向とは、オブジェクトのデータと手続きをクラスという名前でパッケージ化し、クラスの実体であるインスタンスの詳細のデータについてメソッドのみから参照・変更できるようにすることで、インスタンスの内部の詳細は隠蔽して、メソッドのみからオブジェクトを操作するという、オブジェクトのふるまいとしてのプログラミングを、プログラミングパラダイムにするスタイルである、と説明できます。Javaはこのようなオブジェクト指向によって、継承やオーバーライドのような再利用や機能拡張の仕組みと、インターフェースのAPIとプログラムの内部の仕組みを分離し、アクセス指定子によって適切にプログラムを機能拡張などの際に「守る」役割をしてくれます。
また、Javaの良い点は、Java言語の文法やクラスライブラリAPIとして覚えたことが、さまざまなJavaの分野で応用できることです。
たとえば、コマンドラインでの入出力やファイル読み込みのようなクラス機能は、SwingやJavaサーブレットの分野でも、そのまま同じように使うことができます。
変数と型の使い方や、配列とコレクション、それから条件分岐や繰り返し構文、そしてクラスや継承のようなオブジェクト指向の機能は、Java SEとJava EEの多くの分野で、そのまま使うことができます。
また、ScalaやKotlinのようなJavaの変種言語についても、Javaのクラスライブラリがそのまま使えます。
ただし、モバイル機器については注意が必要です。Java MEでは、多くのクラスが制限されており、サブセットによって使える場合と使えない場合があります。それから、AndroidをJavaと言う人も多いですが、AndroidはJavaではなく、仮想マシンやクラスライブラリも異なっています。
また、C++やPythonなどの他の言語を使う場合でも、Javaの経験があるのと無いのとでは大きく違います。ほとんどの文法やオブジェクト指向の機能がJavaと同じだからです。
Javaは、一度勉強するとモバイルからエンタープライズまで多くの分野で活躍できる言語です。また、仕事にありつけることも多く、クロスプラットフォームな仕様からプログラムを動作できる環境も多いですし、ネットや書籍などの情報も豊富です。ですが、いささか古い言語になってきたのは言えるでしょう。Javaと同じ名前がついているJavaScriptは、Javaとよく似た構文を持ち、最先端の機能があります。Javaを習得したら、JavaScriptを次に習得することをおすすめします。今のプログラミング業界では、C/C++とJavaとPythonができれば何でもできるため、C++の習得もおすすめしておきます。
Javaも、最初に登場した時からIT業界はどんどん進歩し、今では古臭い言語になりました。
Javaは、SmalltalkやC++に触発された、オブジェクト指向言語として出発しました。C/C++に近い文法を持ちながら、洗練されたオブジェクト指向を実現し、ポインタを排してガーベッジコレクションという「メモリ管理不要」という特徴を持ちながら、洗練されたオブジェクト指向のクラスライブラリ(NeXTSTEPのCocoaに影響を受けたらしい)を提供し、VMの上で動くことで「再コンパイルの必要がない完全なクロスプラットフォーム」を実現しました。
最初は、Netscapeとの提携もあって、アプレットというブラウザの上で動くJavaの小さなアプリケーションが流行りました。全く違うWebブラウザで動くスクリプト言語であるJavaScriptに同じ「Java」という名前を関したのは、Netscapeとの提携もありますが、アプレットとスクリプトという2つのプログラム領域に共通の名前をつけたかったのではないかと思います。そもそもネットワークで動くことを意図しており、サンドボックス機能で安全にネットワーク上のアプリケーションを動かすことができました。
また、オブジェクト指向としての機能が洗練されており、特にポインタを排しながら継承とインターフェースで多重継承の弊害を無くし、プログラマの間で「オブジェクト指向でなぜ作るのか」という議論を巻き起こしました。
また、Java MEというモバイルやマイクロ製品向けのJavaのサブセットがあり、これを使うことで「デスクトップで開発されたJavaアプリケーションはそのままモバイルでも動く」という特徴を得られ、クロスプラットフォーム性は今でもJavaの優位性として多くの人に評価されています。
そして、CGIよりも効率のいいとされるPHPのように、サーブレットのJavaはスレッドをコンテナサーバで持つことから、CGIよりも効率がいいとされました。サーブレットはJavaのエンタープライズでの利用分野で、IBMのメインフレームでもJava EEのアプリケーションサーバが動きます。
Javaは優秀で、Pythonなどのスクリプト言語よりは高速に動きますし、C/C++のようにメモリ管理を考える必要が無く、そのため安定して「遅くてもきちんと動く」言語です。
また、AndroidのようにJavaを搭載したシステムはどんどん増えていますし、Javaの仕事(求人数)も多いです。(Javaシステムの構築ができるプログラマはハローワークの求人情報でも良く募集されていて、最近はJavaの求人だけではなく、Kotlinのような求人もたまに見られます。Rubyなどの比ではありません。)
ScalaやKotlinのような新技術もあり、これらは変種(代替言語)として動きます。WebフレームワークとしてはStrutsやSpringのほかPlay Frameworkなどもあります。C/C++はメモリ管理などが大変で大規模な開発では動くかどうか心配だが、RubyやPythonを採用するには実績がなく性能がJavaに比べて遅い、などの用途で、「大規模なシステムを作る時の事実上の標準」になってきています。そう、Javaはまだまだ現役です。
ですが、IT業界の時代の流れを考えると、Javaも古くなってきました。特に、Javaはあまりに「クラス」を用いたオブジェクト指向を行いますが、JavaScriptなどでは新しい「プロトタイプ」と呼ばれるオブジェクト指向を行います。プロトタイプチェーンでは、クラスとして型を階層的に書いてインスタンスを発生させるのではなく、プロトタイプを動的に作りながらその型オブジェクトから別のオブジェクトを発生させるという方法で、「委譲」と呼ばれる「メソッドはさまざまなオブジェクトのメソッドに関連付けて動かせる」ということが可能です。
こうしたJavaを新しくしていくために、OracleはOpenJDKとOracleJDKの分岐を作りました。まず、OpenJDKはオープンソースでみんなで開発し、半年という今までよりも短いスパンで新バージョンを投入していきます。その上で、3年おきに有償のOracle JDKを提供し、このバージョンは有料にする代わり8年間のサポートが得られます。こうしたOracleの独自のやり方で、Javaが新しいIT業界の潮流に立ち、「今でも使える新鮮で安定した言語」になることを望みます。
RubyとJavaで悩んでいるのであれば、Javaをお勧めする。Rubyは、少ない行(たとえば3行)でプログラムが作れる、というところが優れているだけで、他にあまり優れた点がない。そもそも、プログラミングなんか最初からしないのがRubyである。また、Rubyは日本ローカルのお遊び言語である。Javaの方が、デザインパターンのようなものも累積されているし、さまざまな用途で応用が利く。Rubyでは、Webアプリケーションぐらいしか開発できない。JavaにはSwingもある。それこそ、Rubyなんか後でもできる。そもそも、ひとつの言語だけを使う人間は少ない。僕の知っている本の著者も、.NETをやりながらPerlも使う。Javaをやりながら、必要に応じてRubyも使えば良い。それこそ、C/C++もできないと、JavaやRubyの言語処理系は作れない。C/C++も必要である。ただ、そんなに簡単に2つも3つも言語は習得できない。まずはJavaから始めよう。
また、Javaについて言うと、「オブジェクト指向を前提とした言語」であると言えます。
RubyやPythonなどは、まだスクリプトとして簡単に書き流す用途に使えますが、Javaは最初からアクセス指定子をつけなければならず、静的メソッドはstatic宣言をするなど、「最初からクラスのインスタンスを作って使うこと」が前提となっています。
そのため、Javaでオブジェクト指向のやり方に逆らってコードを記述するのは困難です。オブジェクト指向言語として使うようにしましょう。
言ってしまえば、Javaでプログラミングを行うということは、そのままクラスの設計と実装をするということです。ここで、「プログラミング=クラス」という関係が成り立ちます。昔のFORTRANのようなフローチャートとアルゴリズムのプログラミングは、Javaでは完全にクラスです。これを毛嫌いせずに、きちんとクラスの設計に取り組めば、プログラミングという一生もののスキルはきちんとつきます。
「初心者にはPythonが良い」とはよく言われますが、僕が思うに、Python(あるいはPHP/Ruby)がいくらか分かってきたら、その後はJavaを学びましょう。
それも、Pythonを完全にマスターする必要はありません。いくらかPythonとプログラミングに慣れてきたら十分です。
Javaは広く使われている言語で、メインフレーム、サーバー、企業システム、あるいはモバイルやGUIアプリ開発にも使えます。
Pythonでプログラミングに慣れたら、次はJavaでさまざまなものを作ってみましょう。それだけで、きちんと仕事になるでしょう。プロとして仕事をしましょう。
また、C/C++もJavaと一緒に学びましょう。GoogleはC/C++, Java, Pythonを三大プログラミング言語としています。言語として優れているのはJavaですが、C/C++はバックエンドなどハードウェアに近いところや、WindowsやUNIXのネイティブアプリケーションの開発にも使えます。C/C++とJavaを使いこなせるのであれば、誰もあなたを素人とは言わないでしょう。
また、プログラミング中級者になったら、自分でアプリケーションを開発すべきです。
この開発で、中級者におすすめなのは、Adobe製品のような「お絵かきアプリ」、Visual Basicのような「言語処理系」、そしてローグライクゲームのような「ゲーム」です。
これらは、一度開発しようと思えばセオリーなども決まっていますし、Webアプリケーションのように開発に必要な敷居も高くありません。
同時に、作っていて楽しいのでおすすめです。Microsoftのビル・ゲイツも、もともとはBASICのインタプリタを作っていました。そこからDOSやWindowsを開発しました。ビル・ゲイツの例は大いに参考になるので、ぜひBASICのような独自のコンパイラを作ってみてください。多くのスーパープログラマは、言語処理系の設計者です。ゲイツに限らず、Perlのラリー・ウォールやRubyのまつもとゆきひろも一流のプログラマで、言語処理系の設計者です。
また、そうしたBASICを使って作るのは、多くの場合ゲームでした。ブラウザを作るのはWebKitを使うだけで楽しくありません。GUIアプリを作りたい人が一番多いと思うので、Adobeのようなお絵かきソフトもそこに加えました。ぜひ、JavaとC/C++で大規模なソフトウェアを作ってみてください。
また、プログラミングの教科書を読むことは、目的ではありません。目的は、あくまでプログラムを作ることです。言語の教科書は参考書だと思って、目の前にあるパソコンのテキストエディタにコードを叩き込みましょう。それをする訓練が大切です。
また、言語はあくまで「ランゲージ」、すなわち「文法上の規則や重要なキーワード」に過ぎません。その規則に従い、規則を守りながら、どのような「センテンス」すなわち「ひとつひとつの言葉を発していく」かは、あなたにかかっています。
特に、お絵かきアプリと決めたからといって、決まりきった「平凡なお絵かきアプリ」を作る必要はありません。あなたの好きなように機能をつけ、フォームなどのデザインを変え、マウスやキーボードに対して反応するようにし、グラフィックスにさまざまなオリジナルの特殊効果を与えれば良いのです。IT技術はまさに「自由」なのです。
Javaには、ポインタがないことで知られる。これは、ある意味、「オブジェクトがあればポインタは要らない」ということを示す一端である。
逆に言えば、「ポインタがあればオブジェクト指向は要らない」とも言える。
ポインタがあれば、ひとつの構造体を複数の関数から使いまわすことができる。これは、オブジェクト指向が目指していることと、全くやり方が同じである。
確かに、クラスの継承のようなことは出来ない。だが、普通プログラミングを行う上で、「ポインタがあればオブジェクト指向は要らない」と言えるだろう。これはLinuxカーネルのように、C言語のままで構造体へのポインタを使いまわすプログラムが多いことで分かるだろう。
もちろん、オブジェクト指向だけがポインタではない。動的な配列を確保したいような場合に、ポインタは必ず必要となる。文字列を表すのにも必要だ。Javaでは、ガーベッジコレクションを導入し、メモリ管理を自動的に「ゴミ掃除をする」ことで解決した。malloc()のあとにfree()をしなくても良い、ありえない言語はJavaの影響である。また、文字列については専用のクラスを用意している。C++にはガーベッジコレクションのような仕組みはないため、自分でメモリ管理をしなければならないが、動作速度を取ると、明らかにC++の方が性能が良いことで知られている。
Javaについて良く似ているのは、シェルスクリプトとよく似ている、ということです。
UNIXではコマンドを使いますが、Javaではクラスライブラリを使います。この時、コマンドは1つ1つ打ち込んで使いますが、Javaはクラスライブラリを使って使います。
そのため、UNIXのコマンドを使うシェルスクリプトと、Javaのクラスライブラリを使うJavaプログラムは、多くの点でよく似ているのです。
特に、splitや正規表現による検索・置換、ソートまで、Javaだけではなく、PerlやRubyのようなスクリプト言語は、「UNIXでコマンドでやっていることと何も変わらない」のです。
よって、UNIXのコマンドを扱うように、Javaのクラスライブラリを使いましょう。JavaプログラマとLinuxユーザーは、やっていることが全く同じなのです。
Javaとは関係ありませんが、LispとJavaScriptも良く似ています。これは、EmacsあるいはNetscapeの内部スクリプトであるという特徴だけではなく、JavaScriptがHTMLをDOMで操作するところが、LispがS式を操作するところと全く同じだからです。
後日注記:Javaとシェルスクリプトが似ていると言えるのは、クラスによるオブジェクトが、ある意味でひとつの「単体のプログラム」のようなものであると考えられるからです。アプリケーションとオブジェクトの単位は、JavaやSmalltalkといったオブジェクト指向の言語では、境界線が曖昧になってきます。オブジェクトがひとつのプログラムであるとすると、Javaアプリケーションは複数のプログラムの集合体であると言えるでしょう。