最終更新日:

Chapter1
プログラミングに必要な知識

1-1 コンピュータの構成要素

コンピュータシステムが、なにでできているかということについて、概念的なことを理解しましょう。パソコンはもちろん、スーパーコンピュータから電子レンジに組み込まれている制御コンピュータまで、基本的な動作原理は同じです。ある程度の原理を知ることによって、プログラミングは理解しやすくなるはずです。

物理的な部品「ハードウエア」

目の前にあるパソコンはもちろん、1つの機器であり、いろいろな部品が集まって作られているのは言うまでもありません。その部品の中でも、キーボードやマウス、ディスプレイは手で触れており、一生懸命見つめているので、これらが中心的な部品であると考えるかもしれません。しかしながら、動作原理を中心に考える場合には、手近なキーボードなどは、むしろ補助的なものと位置づけられます。

コンピュータは、まさに計算機であり、またデータ処理機であることは、すでにこれまでの経験で理解できていると思います。そのような動作をするコンピュータは、「CPU」「メモリ」「I/O」という3つのコンポーネントに分けられます。複雑な構成のコンピュータも、ほとんどの部品がこれらのどこかの分類に入ります。

ハードウエアの構成要素

CPUはCentral Processing Unitの略です。そのまま、「中央情報演算処理装置」などと訳されることもありますが、名前を聞いてもなにをするものかさっぱりわからないという人も多いかもしれません。このCPUが、コンピュータ全体の動作を統括し、計算処理やさまざまなデータ処理を行います。たとえば、Windowsパソコンは一般的にIntel社のCPUを搭載しています。このCPUは、コンピュータの処理能力にそこそこ影響するものですが、代表的な指標は「クロック数」という数値です。この数値が高いほど、単位時間あたりの処理は早くなります。しかしながら、CPUだけですべてが行われているのではないので、クロック数が2倍だからといって半分の時間で終わるとは限りません。いずれにしても、CPUは人間で言えば心臓であり脳であるような部品です。高性能なものはそれなりに高価ですので、高性能コンピュータは高価になります。

Pentium 4(http://www.intel.co.jp/jp/products/processor/pentium4/より入手)

メモリは、記憶装置です。ただ、ディスクやUSBメモリとは違うものを指します。CPUと直接やり取りのできる記憶装置がコンピュータの構成要素としての「メモリ」です。ディスクなどと区別するために「主記憶装置」「メインメモリ」「主メモリ」などとも呼ばれます。このメモリには、データや、後で説明するソフトウエアなどがおかれます。そして、CPUとの間は「バス」という配線があってきわめて高速にやりとりができます。CPUは、メモリからデータを取り出して処理をして、メモリに書き戻す処理をもっぱら行います。コンピュータシステム全体で、このメインメモリがどれくらい搭載されているかということも、性能を計る重要な指標になります。たとえば、512MBなどの数値で示されます。もっとも、現在のほとんどのコンピュータは、CPUとメインメモリとのやりとりをより素早くできるようにするために、あらかじめCPU内部などで読み取っておくという「キャッシュ」という手法が必ず使われています。そのため、メモリといってもいろいろなところにあり、それぞれがシステムの性能を決定づける要素として語られるようになっています。

さらに「I/O」について説明しましょう。これは、Input Outputの略です。構成要素としては、キーボードやディスプレイなどの機器をつなげるための制御装置を指すことが一般的ですが、ここではCPUとメモリ以外で、データを取り込んだり、あるいは表示や印刷するものを総称してしまいます。こうした装置一般は「周辺機器」と呼ばれますが、CPUとメインメモリを主と考えたシステムなので「周辺」と言っているのです。データの入力は「インプット」「入力」、データを表示したり印刷したりすることは「アウトプット」「出力」などと一般的な表現もよく行われます。いずれにしても、いちばん目に触れる中心的な機材は、コンピュータシステムの考え方では「周辺機器」というあたかも脇役的な呼び方がなされているわけです。

コンピュータを動かす「ソフトウエア」

コンピュータを使い始めたら、すぐにきれいなグラフィックスが表示され、インターネットが使える便利な状態になっているため、前記のハードウエアをどのように稼働させているのかということはまったく意識すらしないでしょう。しかしながら、あらためてCPUの動作から検討をしてみます。

CPUは計算やデータ処理ができると説明しました。確かにその能力があるのですが、データを与えればたちどころに結果を出してくれるほど優れた機能は持っていません。データ以外に、そのデータをどのように処理をするかという手順書きもいっしょに与えてやらないとなにもできません。こうした手順書きを「プログラム」と呼ぶのが一般的です。

プログラムは、メインメモリに置かれます。また、データもメインメモリにおいておくのが一般的です。周辺機器のディスク上にあるじゃないかと思うかもしれませんが、現実にはいったんメモリに持ち込んで処理をしてディスクに書き戻しています。いずれにしても、データもプログラムも、メモリが記憶しているものであることに変わりません。言い換えれば、メモリにあるのがデータなのかプログラムなのかは、一見するとわからないのが一般的です。ただ、普通にWindowsを使っているときにはそうした管理をWindowsがしっかり行っているので、滅多にデータとプログラムを間違えることはありません。プログラムというものが、ハードウエアとは別に存在し、それはあたかも「データ」のように存在しています。従って、何らかの方法で、置き換えることができます。ハードウエアの部品を取り替えるよりもはるかに簡単に、メモリ内のソフトウエアの入れ替えができます。こうした仕組みが発明されたことで、コンピュータシステムは飛躍的に機能を向上させたのです。だから、同じパソコンが、ワープロになったり、写真合成機になったりということができるわけです。

こうした置き換え可能なプログラムを、ハードウエアに対比させて「ソフトウエア」と呼びます。プログラム自体、メモリに置く以外にいろいろな記憶方法がありますが、Windowsでは、たとえばファイルとして保存されていると考えてください。もちろん、ディスクというハードウエアは必要ですが、その中に記録した「形のないもの」としてのソフトウエアがあります。ディスクには、データを入れても入れなくても、その形は変化する訳ではありませんし、重さも変わりません。そのため、ソフトウエアは「無形のもの」を総称する言葉にまでなっています。

ソフトウエアとプログラム

どんな手順が作れるのか

CPUに何か処理をさせるには、手順書きとしてのプログラムが必要であることを説明しました。手順の1つ1つのステップで行える内容は、CPUごとに決められています。その1つ1つを「命令」と呼び、どんな命令に対応できるかを一覧にしたものを「命令セット」などと呼びます。Windowsパソコンで使われている各社のCPUは処理できることが共通なので(つまり、共通の「命令セット」を持つ)、IntelのPentiumだけでなく、CeleronやAMD社のAthronなどといろいろなCPUが使われるに至っています。

コンピュータの性能がすばらしいと思っていると、この「命令」もすばらしいものと思うかもしれませんが、意外にもそんなことはありません。単に、2つの数値を四則演算するとか、あっちのデータをこっちに移動するといったことしかできません。1つ1つの命令でできることは非常に基本的なことだけなのです。しかしながら、この基本的な命令を組み合わせることで複雑な計算をしたり、写真を加工するといったことができるのです。

Pentiumの命令セットの分類(ftp://download.intel.com/design/Pentium4/manuals/25366516.pdfより)
分類意味
データ転送メモリやレジスタ間でのデータの移動やコピー
バイナリ演算通常の四則演算など
10進数演算10進数処理のための機能
論理命令ANDやORなどの論理演算
シフト、ローテート2進数の桁で上下にずらす
ビット、バイト演算ビット単位、バイト単位の処理
制御処理ジャンプや分岐、繰り返し
文字列処理バイト列を文字列と見なして処理
入出力処理入出力ポートとのやりとり
浮動小数点演算浮動小数点演算プロセッサを使った処理
MMX命令多数の連続したデータを処理する命令
SSE命令マルチメディアデータを処理する機能

CPUはメモリに記憶してあるプログラム中の命令を、1つずつ読み出してはその通りに実行するのが基本です。メモリのいちばん根本的な機能は、0か1かを覚えるという機能で、その記憶機能が非常にたくさん含まれています。0か1かなので、これは数学的には2進数の1桁で表すことができます。また、このような記憶領域1つを「1ビット」とも言うことがあり、ビットは2進数の1桁と意味的に同じになります。この1ビットを、8つ合わせて「1バイト」という単位があり、これがメモリのごくごく基本的な単位となります。CPUがデータを扱う場合の基本単位も1バイトであることが一般的です。なぜ8なのかということも興味あることかもしれませんが、ここではそういう決まりになっていると考えてください。現在のコンピュータは、アルファベットの1文字を、1バイトで表現し、メモリの中の1バイトの領域を使って記録管理するというのが基本的な方法になっています。

CPUにとっての処理手順書であるプログラムも、結果的に1バイトの領域をたくさん使って記憶します。命令の長さは、Windowsパソコンの場合は可変ですが、1バイト単位の長さになっています。

実際に、CPUが理解できるという意味での命令は、10110011 11001100…のような2進数のものです。この1と0が対応するビットに記憶されていれば、手順通りの作業ができる準備ができているということになります。CPUが理解できるという意味で「機械語」「マシン語」「マシンランゲージ」などと呼ばれています。一般には、2進数表記はややこしいので、16進数で「B3 CC」のように記述されることが多いでしょう。ここでは、2進数、16進数までは理解しておく必要はありません。(ただし、できれば、ある程度の記述ができるまでは学習しておく方が後々の理解は深まるでしょう。)

この機械語は、まったく文字通りの機械のための言語で、人間にとってはまったく理解不可能な言語であるとも言えるでしょう。もちろん、専門家であれば、こうした言語を駆使してプログラムを作ることは可能ですが、現在では、機械語を直接作るという形式のプログラミング作業を行うのは、皆無になったと言っても過言ではありません。もっと、わかりやすい方法でプログラミングを行いますので、機械語そのものについてはいっさい覚えておく必要はありません。概念をしっかり理解しておけばいいでしょう。

機械語のプログラムで、CPUが理解できる形式のものを「実行オブジェクト」や「実行プログラム」という呼び方をする場合もあります。さらに、「オブジェクト」と省略することもあります。後で出てくる「オブジェクト指向」のオブジェクトと、「実行オブジェクト」のオブジェクトは、多くの場合は違うことを指しますが、同じ用語が使われてしまっています。一方、実行可能なプログラムのことを「バイナリ」と呼ぶこともあります。たくさんの呼び方があり混乱の元ではありますが、長年の経緯でいろいろな用語が使われるに至っています。

1-2 プログラミングの必要性

プログラムを作ることを「プログラミング」と呼びます。なぜ、プログラミングをする必要があるのかということを検討してみましょう。

すでに作られているプログラム

パソコンに電源を入れるといろいろなことに使えるようになっています。基礎となるソフトウエアであるオペレーティングシステムのWindowsもプログラムですし、ワープロソフトのMicrosoft Wordもプログラムです。これら、必要なプログラムはすでに作られてしまっているので、プログラミングというのは一部の会社だけでやっていることと思うかもしれません。また、自分で作るなんて考えたこともないかもしれません。

実際、Wordがあれば論文やレポートは作成できますし、Excelで必要なデータ処理ができてしまうと思うかもしれません。実際、こうした市販のソフト(「パッケージソフト」と呼ばれます)を買ってきて、それを組み合わせることでなんとかできてしまいます。たとえば、自動車を考えれば、みんな運転はしていますけども、自動車そのものを製造するのはもっぱら自動車メーカーの役割だと考えれば、パソコンでも同じように「プログラムを使う人」で過ごすことは可能です。

しかしながら、自動車とドライバーのようなハッキリとした切り分けは、コンピュータの世界では必ずしも明確ではありません。たとえば、ある程度の規模のビジネスを行うとき、そのビジネスを効率的に推進するためにコンピュータを活用したいと考えます。そのとき、WordとExcelでなんとかなる場合もなくはないでしょうけど、多くの場合はもっといろいろな要求があり、また、実際の仕事にフィットさせ、効率的に手軽に仕事をこなせるようにしたいと考えます。そのために、独自にソフトウエアを開発するということは一般的に行われています。もちろん、規模の大きなシステムは専門家集団でとりかかります。しかしながら、規模の小さなものや個人レベルの作業となると、その人がプログラミングあるいはそれに近い作業(「インテグレーション」などと呼ばれる場合もあります)を行って、カスタムシステムを組むということが行われています。逆に言い換えれば、こうしたカスタムシステム構築という余地があるのがコンピュータシステムの利点です。Excelしかつかえないわけではありません。もちろん、システム構築には費用がかかりますが、劇的なコスト削減効果が得られることもあり、カスタムシステムはビジネス現場では当たり前に行われています。

このとき、システム構築で行われるのはプログラミングだけではありませんが、単にアプリケーションをそのまま使うということを超える場合、コンピュータをより深く利用する場合のキーワードの1つとして、「プログラミング」とそのスキルや知識は必ず出てくる話題です。

現在のプログラム開発

ややこしそうな機械語を知る必要はないと言いましたが、プログラミングの世界は長い歴史を経て、人間の言語に近い「プログラミング言語」を使って記述できるようになっています。人間の言語に近いということで「高級言語」などとも言われるのですが、普段の日常言語に比べると、機械語よりは若干歩み寄っているだけで、おそらく多くの人にとっては激しく機械向けの言語だと思うでしょう。現在一般に使われているプログラム言語は、いろいろな理由から、記号や数式といった数学的な世界にきわめて近いものになっています。その点で取っ付きにくいと考えるのはもちろんですが、これについては慣れるしか仕方ないでしょう。

日常言語をそのままコンピュータが解釈すればいいではないかと思うかもしれません。実際、そうした試みも研究され続けていますが、現状では実用的なプログラム開発の世界では滅多に使われていません。おおむね、人間の言語に近いと機械語から遠ざかり、実際に稼働させたソフトウエアの性能は高くないのが一般的です。一方、機械語に近いプログラム言語だときわめて効率よくCPUに実行させることができるため、むしろこうした言語を使うのが中心的なやり方となっています。つまり、まだまだ、人間がコンピュータに歩み寄らないと、高度な利用はできないという状況なのです。

一方で、プログラムを書くということに至るまでの、設計のやり方や、あるいは複雑なプログラムを整理して作るための方法など、さまざまな方法論は日々進化しています。また、デザインやワークフローの分析といった純粋にエンジニアリングではないような業務との連携ということもしっかりと意識して開発がされる現在、システム開発は大きなビジネスを生み出しています。

プログラムの学習の目的

プログラムを学習する場合の目標は何でしょうか? もちろん、エンジニアとしての技術を身につけたいということもあるかもしれませんし、Microsoft社に入社して次期Windowsの開発に携わりたいと思う場合もあるでしょう。エンジニアリングレベルでの知識を身につけたい場合には、それなりの勉強をしなければなりません。

一方、エンジニアにならないような人でも、プログラミングに触れておくことで、さまざまなスキルアップが可能です。まずは、コンピュータの原理を非常に深く学習する機会になります。原理を身につけておけば、たとえば、WordやExcelを使うような場合でも、効果的な使い方ができるようになることを期待できます。また、アプリケーションの自動処理である「マクロ」や、あるいは「スクリプト」といった手法をプログラミングの1つとして知っておくことで、日々の業務をより効率的にこなすことができるようになるかもしれません。プログラムを仕事にしない人でも、プログラミングがどんなものかを体験しておくことは、決して無駄な努力にはならないはずです。

1-3 プログラミングの歴史

プログラミングが現在のようなやり方になるまでに、どんな推移をしてきたかを簡単にまとめておきます。

機械語を効率化する時代

最初に説明したようにCPUが理解できる機械語という世界が登場し、当初は機械語を何らかの方法で書いていました。この辺りの、どこまでがハードウエアとソフトウエアの分離がされたかという歴史的な視点での問題はあり、書籍も何冊も出版されているので、興味があればそれを読んでみましょう。最初は、配線をあれこれ変えることで、配線のパターンを機械語にマッチさせて、それをプログラミングとしていました。その後は、電子的なメモリに記録させるために、スイッチ操作やパンチカードなど、さまざまな装置が作られてきています。

機械語のプログラムのイメージ(正しいプログラムかどうかは分かりません)

早い段階から、機械語そのままではなく、機械語の1つ1つに対応する「単語」を記述することで、プログラムを書くということが行われるようになりました。こうした単語を「ニーモニック」と呼び、ニーモニックを駆使してプログラムを記述するための言語を「アセンブリ言語」などと呼びます。たとえば、あるメモリにあるデータを計算するのに「3F 12 5A 82」などと書くのより、「ADD A,20」のような書き方をした方がよっぽどわかりやすいわけです。こうした記号や単語を使って記述するという世界が形作られてきました。

おそらく最初は、アセンブリ言語で書いたプログラムを手作業で機械語にしていたと思われますが、アセンブリ言語でプログラムを作ったものを、記憶装置に入れておき、それを自動的に機械語に変換するプログラムを使うようになりました。こうしたプログラムを「アセンブラ」と呼んでいます。

アセンブリ言語で記述したプログラム(PowerPCというCPUのアセンブリ言語です)

より高度な言語への進化

アセンブリ言語では、機械語と命令が1対1になっているので、CPUを直接動作させるようなものでした。もちろんそれはそれで進化なのですが、100+200+300といった単純な計算でも、アセンブリ言語ではCPUの命令セットを考慮しながらその手順をあれこれ考えて作り込みをしなければなりません。そこで、こうした数式くらいは数式で書いて、それを対応する機械語の命令群に変換してしまうということを考えました。もちろん、変換するのもプログラムの仕事です。こうしたプログラムを「コンパイラ」と呼びます。

最初の言語は何であるかという歴史的な議論も興味あるかと思いますが、実用化という観点も加えると、FORTRANという言語が注目できるでしょう。これは、FORmula TRANsferの略であることからわかるように、数式を変換するというのが当初の目的であることが窺えます。しかしながら、ここで、データを記憶する概念的な対象である「変数」や、条件分岐や繰り返しを含む「制御構造」といった考え方が生まれており、こうした考え方は現在でもプログラミングの基礎となっています。こうした、機械語との対応を離れた言語は、「高級言語」と呼ばれましたが、最近はあまり使われない用語になってしまいました。

こうした言語はその後、たくさん生まれましたが、現在のプログラミングでは、C言語系列のものがもっぱら使われていると言えるでしょう。この講義で説明するJava言語はCの流れを汲みながら改良された言語ですが、プログラム実行のための仕組みが大きく違うので、C言語の系列とはみなされていません。

FORTRANのプログラムの例(USER NOTES ON FORTRAN PROGRAMMING - http://www.ibiblio.org/pub/languages/fortran/unfp.html)
      PROGRAM DOLOOP
C     ------------------------------------------------------------------
      INTEGER
     *          COUNT
C     ------------------------------------------------------------------
      REAL
     *          X, X1, X2, X3
C     ------------------------------------------------------------------
      WRITE (*,*) ' ENTER X1, X2, X3 '
      READ  (*,*) X1, X2, X3
C     ------------------------------------------------------------------
      COUNT = 0
      DO X = X1, X2, X3
        COUNT = COUNT + 1
        WRITE (*,*) ' X=  ', X
      ENDDO
C     ------------------------------------------------------------------
      WRITE (*,*) ' COUNT=  ', COUNT
      WRITE (*,*) ' N=      ', MAX(0, INT((X2 - X1 + X3) / X3))
      WRITE (*,*) ' LAST X= ', X
C     ------------------------------------------------------------------
      END

構造化プログラミングからオブジェクト指向へ

高級言語の登場で、プログラミングの開発効率は飛躍的に高くなりましたが、巨大化したプログラムのメンテナンス性が問題になるようになりました。たとえば、同じような処理がプログラムのあちこちにある場合、それぞれでそれなりに記述していたとします。しかし、そのやり方をちょっと変えないとまずいとなったとき、プログラムのあちらこちらをそれぞれ適切に変えないといけません。言葉では簡単にそういうことで済んでしまいますが、現実にはそんなことを完全に行うということは不可能に近いことです。そこで、プログラムを分解することで共通の処理などを洗い出し、それらの階層関係を明確にした上で、プログラムを小さな単位ごとに完成させて行くという手法が登場しました。そうすれば、問題が発生したときにどこに手を入れるかと言ったことが明確になり、より大きなプログラムの構築に道筋をつけたのです。

こうした考え方は、今でも有効です。プログラム全体を設計するときの基礎的な考え方として、全体から細部に向かって分析を進めて、共通に行える作業は1つのプログラムでもっぱら行うようにします。そうした、1つのプログラムを「サブルーチン」と呼びます。プログラムを作るときに、サブルーチンをまずは設計して作り、それをさらに組み合わせるような流れで全体のプログラムを作り上げます。こうすることで、プログラム全体を破綻することなく管理し、そして不具合が限りなく少なく、意図した通りに動作するプログラムを作るという考え方です。この方法は「構造化プログラミング」と呼ばれています。

構造化したプログラミングの概念

さらに進化したのが「オブジェクト指向」という考え方です。この考え方は非常に多岐に渡るもので、ここで完全に記述することは難しいことですので、エッセンスを紹介したいと思います。オブジェクト指向でのポイントは、処理を手順として考えるだけでなく、処理対象に対して何かをするという考え方を基本とします。それまでのプログラミングは、データと処理手順が別々にあることが基本でした。オブジェクト指向では、データが自分に対する処理を知っているという考え方のもと、データに対して処理を依頼するという考え方を行います。その意味では「データ中心」という表現もオブジェクト指向の側面を示すものです。

オブジェクト指向の考え方

こうした考え方に加えて、処理対象の性質を引き継ぐ新しい形のデータを定義するなどといった高い拡張性を持たせることなどができるようになり、構造化の時代よりも遥かに巨大なプログラムを高い品質で開発できるようになりました。また、オブジェクト指向の考え方を言語仕様に盛り込んだ言語が登場し一般的に使われています。オブジェクト指向という考え方は、現在では当然のことになっていますが、それをきっちりと組み込む場合もあれば、ゆるやかに取り込まれた開発システムもあるなど、実現方法には幅があると言えるでしょう。

1-4 Javaという言語

この講義では、Java言語でプログラミングを説明します。Javaが登場した背景と特徴などをまとめておきましょう。

Javaが登場するまで

80年代の後半から90年代にかけて、C言語が開発言語の定番となりました。構造化が可能であり、シンプルで効率的なプログラムの作成ができるという点が受け入れられました。それまではアセンブラから高級言語への流れを受け、さらに人工知能などと騒がれた時期もあって、より自然言語に近いプログラム言語ということに注目はされていましたが、日常言語に近づけたからといって開発効率が促進されるとも限らず、結果的に作成したプログラムのスピードやあるいは最適化ができるという意味で、日常言語に近づくという路線は一定のところで限界になっていました。

そのような中、オブジェクト指向へのシフトで、C++という言語が主流になりつつありました。C言語をもとにしてオブジェクト指向プログラミングのための機能が組み込まれたもので、現在でもWindowsのアプリケーションプログラミングでは主流の言語ではあります。しかしながら、C++はある種の複雑さも併せ持ってしまいました。また、C言語での問題を引きずるなど、議論の的になる言語でもありました。しかしながら、Windowsでの中心的な開発言語だけに、もっともメジャーな言語になっているとも言えます。

ネットワークプログラミング言語としてのJavaの登場

一般に複雑なものよりは、シンプルなものの方が浸透します。JavaはC言語をベースにした仕様ながら、オブジェクト指向を最初から考慮し、C++での問題とされたことを克服すべく、シンプルで強力な言語として登場しました。ちょうど、インターネットの普及が目前だったこともあって、ネットワークのプログラミング機能を最初から含むような印象を受けるマーケティングも功を奏し、1995年のリリース時には爆発的なブームになりました。

いろいろな特徴があるのですが、まず1つは、「アプレット」というネットワーク経由でダウンロードして実行するプログラムの形式をサポートしていることがあります。これまでは、ソフトウエアは、パソコンにインストールして使うものだったのですが、アプレットの登場によりインターネットの先から取ってきたプログラムの実行ができるようになります。インターネットの大きな可能性を具体化するものとしても注目されました。そして、インターネットはWindowsだけが使えるものではありません。アプレットをダウンロードするのはどんなパソコンで、どんなオペレーティングシステムの上で動いているかもわかりません。そこで、CPUやオペレーティングシステムに依存しないでプログラムを実行させる方法を、Javaでは実現したのです。

どんなOSの上でも動くソフトウェア

Windowsが使えるパソコンがたくさん売れたので、世の中にはWindowsしかないと思うかもしれませんが、そうではありません。コンピュータ機器はたくさんあります。OSで言えば、Mac OSや各種のUNIXがありますし、電子手帳的な携帯端末には多種多様なものがあります。これらは、Windowsとは別のOSであり、Windowsで使われているIntel社ないしはその互換CPUが使われている可能性はむしろ少ないと言えるでしょう。Windows用のワープロソフトは、そのままでは他のOS、たとえばMac OSや電子手帳のザウルスでは動かないのです。

しかしながら、サンマイクロシステムズはJavaを開発するに当たり、こうした常識をくつがえすような機能を盛り込みました。ある1つのプログラムが、一定の条件を満たせば、WindowsでもMac OSでも、あるいは携帯端末でも動くような枠組みを考えたのです。OSもCPUも違うのに、なぜ同一のプログラムが機能するかですが、簡単に言えば、OSやCPUとは独立した仮想的なコンピュータを定義して、そのコンピュータを各種OS上で利用できるようにし、見かけ上、OSやCPUの違いをなくしてしまうというものです。こういった仕組みを「バーチャルマシン」あるいは略してVMと呼んでいます。そのVMで実行可能なプログラムを作るための言語が、まさにこの本で紹介しているJavaなのです。

こうしたことを実現するメカニズムは相当複雑なのですが、ポイントは、仮想的なコンピュータを、ソフトウェアを使ってあたかも存在するかのようにふるまわせているというところです。こうした技術はエミュレーションなどと呼ばれます。従って、Java VMそのものは、OSあるいはCPUごとに別々のものが必要になるのですが、そのJava VM上では、CPUやOSによる違いはないわけです。

インターネット上のソフトウェアをJavaは実現する

インターネットのしくみはよくご存じだと思いますが、大きな特徴として、ネットワークの向こうのサーバーにある文書や画像のデータをクライアントに取り込む、つまりダウンロードして参照できるということがあげられます。

サンマイクロシステムズは、Javaのソフトウェア上でも、こうしたダウンロードして実行できるというメカニズムを可能にしました。こうした形態のソフトウェアを「アプレット」と呼んでいます。アプレットはJavaのプログラムで、一般には独立したファイルに保存されています。そのファイルをサーバーにアップロードしておきます。そして、クライアントで実行する指定があれば、サーバーからダウンロードして、クライアント上でプログラムが実行されます。

Webブラウザは、OSに依存しないで同じように文書を参照できるというのが当初からの目標です(最近はそれも崩れつつありますが)。従って、アプレットも動作条件を選ぶということはお門違いということになります。そこで、ブラウザにJava VMの機能が組み込まれていれば、同一のJavaアプレットが、異なるOSあるいは異なるCPU上でもまったく同じように動作することが期待できるわけです。90年代後半当時の2大ブラウザであるNetscape NavigatorとInternet ExplorerはJavaの登場と同時にJava VMを搭載しており、そのこともあって、Javaが登場した当時は大きくクローズアップされたのです。

普通のアプリケーションは、基本的にはパソコンに接続されたハードディスクに存在していないと一般には起動できません。しかしアプレットは、手元に実体がなくてもネットワークがつながっていれば、それで利用できるのです。こうしてJavaをベースにしたコンピュータ環境は、従来にない世界を構築したということなのです。

不安定要素の排除

C言語の大きな問題は、複雑なデータの扱いにありました。データは、メモリに展開されますが、C言語では、「メモリを使います」「メモリはもう使いません」といった指定をきちんとプログラムの中で行わないと、実行途中でクラッシュしてしまうという現象に遭遇します。そうした手順がプログラムに複雑に入り組むと、メモリの管理はもはやプログラムの中で完全にまかないきれないくらい複雑にもなりがちです。オブジェクト指向によりそうした問題はある程度整理はされるのですが、それは根本的な解決にはなりませんでした。

しかしながら、Javaはそうしたメモリの管理をおおむね自動化しました。通常はそういうことを意識する必要はなくなったのです。これは、使わなくなったデータのメモリを自動的に解放するという仕組み「ガベージコレクション」を、Java VMが実現しているからなのです。C言語のそうしたメモリ管理の難しさは「ポインタ」というデータの扱いに集約されます。ポインタとはデータのありかを示すデータで、ある意味、住所を覚えるものと考えていいでしょう。しかし、このポインタの扱いの習得はかなり難しく、現在でもここを習得していないにもかかわらず“プログラマ”を名乗るような人もいないわけではないくらいで、逆にそれは開発現場では問題となっています。しかしながら、Javaはそうした知識はまったく不要と言えるほどです。メモリ管理をしなくても、安定したプログラムの作成ができるのです。C言語はそうはいかないので、その意味で習得のしやすさもあるということです。

ライブラリと言語の統合

プログラミングとなると、どうしても「言語」が主役に思えるかもしれません。では、C++を学習すればWindowsのプログラミングがすらすらできるかと言えばそうではありません。たとえば、ウインドウを表示して、その中にボタンやテキストフィールドを置きといった具体的な作業は、C++の言語として定義されているわけではありません。そうしたことはWindowsのシステム機能を使わないといけないのです。Windowsのシステム機能と言語とは全く別です。結果的にC++で書かれたアプリケーションは、確かにC++のプログラムですが、その中の多くは「Windowsの機能を呼び出す」ということに終始します。

こうした言語に定義されていない機能を使うための手法はいろいろあるのですが、「ライブラリ」と総称されます。つまり、「Windowsシステムの機能を使うライブラリ」と自分で作ったプログラムを組み合わせることで、Windows上で稼働するアプリケーションを作成できるのです。実際のプログラムでは、言語そのものの知識とライブラリの知識はどれくらいの割合で使われるかは、もちろんアプリケーションによっては違うもののライブラリの知識のほうが10倍は多く使うものと思われます。本来は、言語よりもライブラリの方がその意味ではプログラミングの世界では主役と言えると思います。

Javaはそういう事情も考慮して、言語に加えてライブラリも当初から標準化したものがリリースされ、その意味では、言語とライブラリを統合したものを「Java」と呼んでもおかしくないという状況になりました。そのライブラリも、オブジェクト指向という特徴に加えて、プログラム実行時にライブラリと合体するという特徴も持っていました。それまでのソフトウエアは、ライブラリとあらかじめ合体させておくのが常識でしたが、そういう点でも常識をくつがえしたのです。こうした仕組みがあるから、アプレットやJava VMによるオペレーティングシステムの依存をなくすといったことができるようになったのです。

その後のJava

95年に登場したときにブームになったJavaですが、そのブームも長く続くことはありませんでした。しかしながら、現在でも、Javaはサーバで稼働するアプリケーション(「サーブレット」と呼ばれます)の開発ではよく利用されているものとなっています。ブームが去ったのは単に世間が飽きてしまったということではなく、覇権争いの結果であるとも言えます。

Javaの登場の頃、NetScapeというWebブラウザが大きな話題をさらっていました。巨大な成長を見込めるインターネットのもっとも注目できるサービスであるWebに欠かせないブラウザでいちばんの支持があったのです。NetScapeはJavaを積極的に取り込んだこともあって、お互いにブームの相乗効果が出ていました。しかし、そうした大きな市場を見逃さないのがMicrosoftです。Windows 95のリリース時にはおまけ程度のネットワーク機能しかなかったものの、急いで出した追加ソフト集にブラウザのInternet Explorerを組み込み、その後のOEMリリースなどでは標準でInternet Explorerを組み込みました。さすがに、Windowsに標準のソフトには太刀打ちできません。折しもパソコンが家庭などにも広く普及した90年代後半は、わざわざブラウザをほかから取ってきて入れ直すような積極的なユーザの比率はどんどんと落ち込み、自動的にInternet Explorerのシェアが上がって行ったのです。

Internet ExplorerはJavaをサポートしていました。Java自体も初期のブームからそれほど時間をおかずにかなりの機能アップをした「Java 2」というバージョンをリリースしています。ところが、Internet Explorer自体はJava 2をついにサポートすることはなく、Sun Microsystemsが自分でInternet Explorer対応をすることになります。これも微妙なところではありますが、もし、最初からInternet ExplorerがいっさいJavaには対応しないでいれば最初からSunがInternet Explorer対応に力を入れていたと思います。しかしながら、微妙なタイミングで、多くの人が使っているInternet Explorerで最新版のJava 2が使えないという状況が続き、ブームの終焉もあいまってマイナスのイメージになっていたとも言えるでしょう。Microsoftが意図的にこうしたことをやったのかは定かではありませんが、結果的に空白期間を作ったことで、Javaのインターネット進出を足止めした結果となったと言えます。

一方、こったアニメーション的なことは、JavaよりもFlashを使った方がより簡単に行えることがあり、Javaが目指していた1つの用途である「ブラウザでプログラムが動く」ということの多くの側面をFlashに持って行かれてしまったことがあります。MacromediaはInternet Explorerをはじめ、各社のブラウザで積極的にFlashが動くように努力したことも大きいでしょう。こうして、Javaの適用範囲は狭くなったのです。結果的に、現在ではアプレットは限られた用途にしか使われなくなっています。

Javaを学習する理由

講義で教える言語がなぜJavaなのかということは、次のような理由があるからです。まず、Javaは過去のさまざまな言語を考慮して作られたシンプルな言語であることから、学習にも適しているということが挙げられます。さらに、講義では、JBuilderというアプリケーションを使います。プログラミングはエディタさえあればできるという意見もあるかもしれませんが、JBuilderのような開発に必要な機能がパックになっているアプリケーションを使う方が、より手軽にプログラミング作業ができます。また、プログラムの間違いもより的確に指摘してくれるので、プログラムそのものに集中することができるからです。

もっともデメリットもあります。まず、Javaはシンプルだとは言え、その全貌をすべてを限られた時間では説明はできません。従って、プログラムの一部は、「ともかくそう書けばいい」という、いわば付け焼き刃な理解でやりすごしてもらう必要があります。細部にわたって解決できないと先に進めない人にとってはつらいかもしれません。その意味では、ほかの言語もあるのではないかという意見もあるのですが、プログラミングでの考え方と本質に少しでも近づき触れるということを考えれば、前述のメリットを注目したいと考えます。

講義ではJavaのすべてを学習することはできません。半分どころか、ほんの入り口だけしかみることができません。それでも、プログラミングの世界を垣間みて、そして自分でプログラムを作り、苦労して完成させるという経験は、これからコンピュータをいろいろな形で活用するときに必ず糧になっていると思います。Javaを勉強するのですが、会得するのは言語そのものではなく、プログラミングという行動からコンピュータの本質に迫るのがいちばんの目的です。