やり直しJava

特徴

Javaの特徴

登場当時(1996年)

Javaの最初のバージョン、JDK 1.0は1996年にリリースされました。それ以前のさまざまなプログラミング言語の良い部分を引き継ぎ、特に構文はCやC++から多くを引き継ぎつつも 複雑さを排除するように設計されたオブジェクト指向言語で、当初は次のような点がセールスポイントとして挙げられていました

  • Java仮想マシン上で動作するため、プラットフォームに依存しないアプリケーション開発ができる
  • Java仮想マシンに搭載されるガベージコレクタにより メモリ管理の負担が大幅に軽減される
  • 言語仕様でスレッドをサポートしており、並列処理の実装が容易
  • ライブラリが充実しており、特にネットワーク機能が充実していて分散オブジェクト環境の開発が比較的容易に行える

当時主流だったCやC++に比べると 仮想マシン上で動作するため実行性能は劣りましたが、これらの点によりソフトウェアの生産性を飛躍的に向上させることができ、基幹システム等の大規模システムに採用されるようになりました。

登場から20年後

現在(2018年)においては、RubyやPythonといった他のメジャーなプログラミング言語でも ガベージコレクタ・スレッドサポート・充実したライブラリといった機能はごく当たり前のように実現されていますし、メジャーな言語は広範なプラットフォームでサポートされているため、先に挙げた点はJavaの特徴として挙げるには相応しくなくなってしまいました。

各言語がどういった分野に強みがあるかという観点で見てみると、Ruby(Ruby on Rails)は中小規模システムのRAPID開発の分野に強く、Pythonは科学技術や人工知能の分野に強みがあります。Javaは組み込みシステムや携帯端末、企業等の大規模なシステムで採用されることが多いです。これはJava言語の特徴というより 組み込みシステム向けのJava MEや小~大規模サーバシステム向けのJava EEの存在が大きいと思われます。多く採用されている分野という観点での特徴をまとめると次のようになります。

  • 組み込みシステムや携帯端末で多く採用されている。
  • 特にAndroid端末で開発を行う場合は Javaまたは Javaと互換性の高いKotlinが採用されることがほとんど。
  • 小~大規模サーバシステムで多く採用されている。

他の言語との比較

単純に言語の比較をしてみると、CやC++に比べると実行性能を犠牲にする代わりにポインタの隠蔽やガベージコレクタの搭載により安全で堅牢なプログラムを作成し易く、豊富なライブラリによりソフトウェアの生産性を上げることができます。実行性能については JITやJava仮想マシンの性能向上により 当初に比べてCやC++との性能差も小さくなってきました

一方でRubyやPythonに比べると、データやオブジェクトの型を明示的に宣言する静的型付けを採用していることにより、開発スピードや柔軟性の面では劣るものの、プログラマの意図が伝わり易く実行前のコンパイル段階で型の整合性チェックを行うことができ、安全性や堅牢性を上げることができます

上記のような点から Javaはバランスの取れた言語だと思います。

Java」(Wikipedia)

Javaと互換性の高い言語

Javaは長年の時を経て進化してきましたが、過去のバージョンとの互換性を保つことを重視してきました。仕様変更や機能追加を行う場合は 過去のバージョンとの互換性を保つような工夫がされてきました。

例えば総称型を導入した際には 過去のバージョンと互換性を損なわないために 型指定のない原型(raw type)を用意しました。また、ラムダ式を導入した際には 関数という概念を新たに言語仕様に追加するのではなく、抽象メソッドを1つだけ持つインタフェース(関数型インタフェース)と匿名クラスを組み合わせることにより オブジェクト指向の枠組みの中で関数型言語の機能を実現してきました。

一方で 互換性を損なわずに機能全体を実現することはできず、部分的に実現された機能などもあります。例えばnull安全ではnullableとnon-nullのデータ型が必要ですが、既存のデータ型をnon-nullに置き換えるにはあまりにも影響が大きいのでnullableを扱うOptionalクラスのみが実現されました。そのため、null安全の機能については不十分と言わざるを得ません(詳しくは「null安全」の章で説明します)。過去のバージョンとの互換性を保つために 有用ではあるけれども取り込めない機能や部分的にしか実現できないような機能があり、Javaが進化する上で1つの足枷となっています

また、他のプログラミング言語と比べるとコードの簡潔性に劣ります。Javaは比較的構文の省略が少ないため コードが冗長になりがちです。例えば次のような点が挙げられます。

  • 文脈から変数の型が明確な場合でも型宣言の明示が必要。近年ではJavaも型推論の機能を部分的に取り入れていますが、それほど賢いものではありません。
  • 検査例外のスローが宣言されていれば、文脈的に例外が発生しないと分かっていても例外処理を記述しないといけない。
  • if文などの条件式には真偽値のみしか渡すことができない。(多くの言語では0やnullを真偽値の代わりにすることができます。)
  • 文末のセミコロンが省略できない。

Javaが比較的冗長と評価される要因としては、言語仕様とは別に クラスや変数などの名前に内容を表すための(長めで)分かり易い名前を付けるというコミュニティの慣習による部分もあります。

1つ1つは小さな違いでも、数多く積み重なるとそれなりにインパクトが出てきます。(しかし、省略が少ないとコードが冗長になりがちな反面、コードリーディングの間違いが生まれにくいというメリットもあります。)それでも 部分的に型推論を取り入れたり、シンタックスシュガーを取り入れることによって幾分コードを簡潔に記述できるようにはなってきましたが、他のスクリプト言語や関数型言語に比べると 簡潔性という点では劣っていると言わざるを得ません。

このような背景から Javaを置き換えるような言語がいくつか登場してきました。ここでは Javaと互換性の高く Javaの後継候補と呼ばれるような言語を3つ紹介します。

Groovy

Groovyは2003年頃に登場したJavaベースのスクリプト言語です。RubyやPythonのようなスクリプト言語に触れると Javaでもこんな風にできたらもっと簡易にコーディングできるのに…と思うような点が多々ありますが、そのようなスクリプト言語に良く見られる便利な特徴が取り入れられています。いくつか具体例を挙げると 次のような点です。

  • スクリプト言語らしく変数宣言も型宣言も不要。
  • リスト(配列)とマップ(連想配列)が用意されている。Javaの配列と異なり、多様なメソッドが用意されている。(Ruby・Python・Javascriptの配列・連想配列のように多機能)
  • if文などの条件式の値として0やnullを真偽値の代わりにすることができる。
  • 正規表現を行うための演算子(=~や==~など)が用意されている。
  • 検査例外処理を省略できる。(便利な反面 堅牢性を損なわないよう注意が必要)

また、関数型言語で良く取り入れられているクロージャや、メタプログラミングの1つであるオープンクラスといった機能も取り入れています。Javaで記述できることは 一部の例外を除き基本的にGroovyでも記述することができます。また、GroovyからJava SEのAPIやサードパーティー製のライブラリを呼び出すこともでき、Javaとの親和性が非常に高いため Javaプログラマにとって取り組み易い言語であると言えます。

更に、Grailsという Ruby on Railsライクなフレームワークを利用して RAPIDなWebアプリケーション開発を行うこともできます。

Groovy」(Wiki)
メタプログラミング」(Wiki)
Groovyってどんな言語? JavaプログラマのためのGroovy入門」(CodeZine)

Scala

Scalaも同じく2003年頃に登場してきた オブジェクト指向言語と関数型言語の特徴を統合したプログラミング言語です。Javaをベースとしたオブジェクト指向言語の上に関数型言語の機能を実現していて、JVM上で動作しJavaのライブラリを利用することもできるため、better Javaとして利用することもできます。一方で 関数型言語の機能や特徴を豊富に取り入れているため、本格的な関数型プログラミングを行うこともできます。関数を第一級オブジェクトとして扱えることは勿論のこと、case classによる代数的データ型、強力なパターンマッチング型クラスモナド構造などの機能を備えています。

Scalaをbetter Javaとして利用することもできますが、通常Scalaを使ってプログラミングを行う場合は関数型言語の特徴が色濃く表れるため、関数型言語に不慣れなJavaプログラマは戸惑うかも知れません。例えば 変数やオブジェクトは不変か可変かを明確に区別していて、基本的には不変を中心に組み立てます。これはオブジェクト指向言語に慣れた人から見ると違和感を感じるかも知れません。これに関連して ループよりも再帰が好まれます。ループでは可変な変数を使わないと表現できない処理でも、再帰では可変な変数を使わないで表現できることもあります。また、文を組み立てるのではなく、値を返す式を中心に組み立てます。手続き型の言語では 処理の流れに沿って文を組み立てますが、関数型言語では問題を分解して各々関数として表現して それらを組み合わせるというアプローチを取ります。Scalaはbetter Javaとしても使えますが、本来の力を引き出すには関数型言語の特徴や機能を理解する必要があります。

Webアプリケーション開発を行う場合には Play Frameworkというフレームワークを利用することができます。

Scala」(Wiki)
ドワンゴ 研修資料
Scala」(ひしだま’s 技術メモページ)
業務でも使えそうなScalaz」(Qiita)
Haskel超入門」(Qiita)

Kotlin

KotlinJavaをもっと簡潔・安全になるように改良した産業利用向け汎用言語として Jet Brains社によって開発されました。登場時期は2011年頃で比較的新しい言語です。Java言語に望まれてる機能であっても 過去との互換性を保つために実現できない機能や 将来Javaで実現が予定されている機能のうちから 有用と思われるものをいくつかを採用しています。また、先に登場したGroovyやScalaからも 機能や簡易記法などを取り入れています。Javaと同様 Java仮想マシン上で動作します。Androidの標準的な統合開発環境であるAndroid Studioにおいて、Javaと並んで標準開発言語の1つとしてKotlinが採用されています。

Kotlin」(Wiki)