Mr.Hack | ||
Mr.Hackです。Javaの勉強はどうですか?4月は飲み会が多くて勉強できない?お気持ちお察しします。でも、毎日毎日がプログラミングですよ。一時間?いや30分Javaにふれる時間を作ってくださいね。それもだめなら、メールを読んだそのあと1時間だけ。Mr.Hackも昔何かで呼んだか聞いたかしたんですが、人間の忘却線というのは、日を過ぎて行くにつれ、急激に放物線を描いたように落下していくようです。すぐにリカバー(復習)すると忘却線は緩やかになるそうです。通勤中・登校中でもかまいません。ちょっとJavaにふれていきましょう。 ところで、今回からぐぐーっと読者の方が増えました。初めてご覧になる方は、是非バックナンバーに目を通しておいてくださいね。結構このメルマガを通して必要なことが書いてあります。 前回で一つだけ修正した方がいいなと思ったところがあります。二つ目のJavaファイルをHelloWorldDemo1.javaからHelloDemo2.javaとした方が初心者の方は復習もかねて見直しができると思います。クラス名もそれに伴い、HelloWorldDemo1からHelloDemo2としておいてください。HelloWorldDemo1でも問題はありません。たぶん最初のHelloWordDemo1を上書きしないといけなくなったでしょう。HelloWorldDemo2.javaは、こんな感じになります。 【HelloWorldDemo2.java】 /** /** ━━━━━━━━━━━━ ここまで ━━━━━━━━━━━━━━━━━━ ここで、一つだけフォローアップ。 main()メソッドのパラメータ(parameter)は、String args[]でもいいの? いいですよ。コンパイルは可です。でも優では、ありません。何故だと思います?下記の例を見てください。 String testValueForMyFirstClassInJavaCafeBreak003[]; 上記二つは同じことをしています。Javaでは、変数もStrong Typled Languageでしたね。この長い変数、testValueForMyFirstClassInJavaCafeBreak003も型(type)が必ずあります。そこで、以前こんなことを言ったのを思い出してください。int型とint[]型は違う、と。ここでも同様です。String型とString[]型は区別されるのです。でもどうでしょう。1行目の方は、ぱっとみ、Stringのところをみると、String型のようにもみえますね。これを書いたあなたは、いいでしょう。しかし、書いてから時間が経過していたり、他人が見たりしたら、誤解を招き兼ねません。そういうわけで、2行目の表記の方がすぐれていますね。 もう一つの理由としては、配列は、 String[] args = new String[10]; のように初期化されますが、その配列をメソッドに渡したりする場合、例えば、 objects.doMethod(args); とします。また、そのargsが新たに参照し直す場合、例えば String[] args2 = new String[10]; とします。このとき、argsを初期化した後に、argsだけを使います。そのため、args[]とすると、Javaに不慣れな人は、args[]が変数だと勘違いしてしまう場合があります。 objects.doMethod(args[]); とはできませんので、注意してください。
前置きが長くなりましたが、前回の宿題の回答へいってみましょう。 答え:PrintStream クラス 皆さんの出した答えと同じですか?どうやって見つけましたか?え?元々知っていた?それは素晴らしいです。でも、もし初めて見たクラスにメッソッドを適用していたらどうしましょう? そうです。 GO TO "Java API"です。
もうすでに、APIをダウンロードして自分のコンピューターにインストールしましたね。まだしてない方は、vol.000にかいてあるファイルをダウンロードするか、LINKをブックマーク(お気に入り)しておいてくださいね。自分のコンピューターにインストールした方も、ブックマークに入れておくと便利ですよ。ブックマークに入れる方法は、ブラウザーを立ち上げて、ファイルからファイルを開いてJava APIをインストールしたフォルダ(通常は、Java SDK以下のjdk1.3.1\docs\ja\api\index.html)にindex.htmlを選択します。そうしますとローカルでJava API を見ることができます。 開きましたか?開くと三つのフレームに分割されていると思います。左上がJava の全てのクラスへのリンクとパッケージ、左したが全てのクラスネーム、そして右のメインウインドウは、クラス等をクリックしたときの、その詳細ですね。 Systemクラスを探したいときはどうしますか?そう、左下の全てのクラスの中からSystemクラスを探します。そのフレームを結構スクロールしないといけなさそうですね。なぜなら、アルファベット順にならんでいますから。Mr.Hackはいつもブラウザの検索機能を使って目的のクラスを見つけます。例えば、Internet
Exploreだったら、左下のフレームの中のいずれかを一回クリックしてカーソールをそのウインドウないに移して、Ctrlキー + Fで検索ウインドウが現れ、そこにsystemといれてMatch
whole word only(英語版のため。日本語版だとなんて訳してあります?)にチェックを入れて検索します。そうするとドンピシャリ、見つかったでしょ?そしてSystemリンクをクリックしてみてください。そうすると右メインウインドウにSystemクラスが現れましたね。 ざっと目を通しましょうか。そこには、クラスの要約から始まって、フィールドの概要, メソッドの概要、そして、スクロールをしていくと各フィールドとメソッドの詳細情報があります。もう一度Systemクラスの一番上までスクロールUPして頂いて、少しだけ下がるとフィールドの概要のテーブルのなかにoutがありますね。その左のセルには何が書いてありますか?そう"static PrintStream"とあります。そのPrintStreamをクリックしてください。PrintStreamクラスがひらきましたね。それが、答えです。そのメソッドの概要を確認してみましょう。そのテーブルの中に、printlnがあると思います。それのprintln(String s)というのが、あなたが使用したメソッドです。 さて、ここまで呼んだときに??????となってしまった方もいるでしょう。まず、どうやってSystemがクラスってわかったの?そもそもクラスって何?Systemとoutの間にある点(ドット)ってなに?System.out.printlnってなに?これって覚えるしかないの?SystemクラスのField Summaryに出てきたstatic Printstreamの staticって何??・・・。 一つ一つ見ていきましょう。
HelloWorldDemoプログラムを見てみましょう。 class HelloWorldDemo { 上記の例でいえば、最初のclassから最後の}がクラスです。Javaにおいては必ず一つクラスがあります。その中に、メンバフィールド(member field、単にfield、またはinstance variable)があり、メンバメソッド(member method、単にmethod(C,C++ではfunction))があります。 class HelloWorld { 上記の例で言えば、Stringタイプの変数messageがメンバフィールドで、戻り値がStringタイプのgetMessage()がメンバメソッドに当たります。このHelloWorldクラスはフィールドのmessageに”ハローワールド”を格納していて、それをgetMessageというメソッドでStringタイプの"ハローワールド”という値を取り出すことができます。戻り値とは、アウトプット(結果)と解釈するとわかりやすいでしょう。このクラスはハローワールド製造器という青写真(設計図)で、この設計図を元に(このコードを元に)オブジェクト(実体)を作っていきます。そのオブジェクトにgetMethod()を適用することによって、ハローワールドという文字列を製造してくれます。実生活にある例を挙げれば、たい焼きを想像してください。”およげたい焼き君”なんていう一世を風靡した曲がありますが、あの鉄板の上でたい焼きを製造するのを思い浮かべてください。たい焼きを製造する鉄板の型がクラス(青写真、設計図)で、実際に製造(生成)される”たい焼き”がオブジェクト(実体)です。そのオブジェクト(たい焼き)には、あんこが入っていますね。あんこがメンバフィールド(フィールド)です。どのたい焼きにもあんこが入っているように、同じクラスから作られたオブジェクトにはどれもおなじフィールドが含まれています。this.はそのクラス(設計書)から生成されたオブジェクト(実体)自身を指します。つまり、たい焼きが鉄板の型からできたときに、この(this.)たい焼きにgetMethod()を適用して、あんこ(message)を得ます。 たい焼きの例は、Mr.Hackオリジナルなので参考書には出ていませんよ。でも、イメージしやすいと思いませんか。およげたい焼き君をテレビの前で歌っていた世代ですからね。もしどこかで、たい焼き君を見つけたら、それは、Mr.Hackのパクリです。今川焼きはどう?それも、パクリですよ。 え、ちょっとまった!たい焼き、あんこ云々はわかったけど、実際にプログラミングではどうやって、そのオブジェクトってやつをつくるのよ? ■参照変数 もう、みんさんは前回の例でそれを体験しています。 class HelloWorldDemo { の中の、 HelloWorld myClass = new HelloWorld(); がそうです。HelloWorldクラスのオブジェクト、myClassをnewによって、生成(初期化)しましたという意味です。C++プログラマーの方は"new"というものは、もうおなじみですよね。そう、メモリーアロケーション(Memory Alocation、メモリー確保)です。 HelloWorld myClass; は最初の例と同じ意味ですが、こっちの方が考えやすいと思います。一行目でmyClassというオブジェクトの参照変数(reference variable、または、インスタンス変数(instance variable))を作り、二行目のnewでオブジェクト自身を作ります(オブジェクトにメモリースペースを割り当てます)。厳密にはnewでHelloWorldクラスのオブジェクト用に確保されたメモリースペース(下記の図2の右側の箱)をmyClassがrefer(参照)します。 @HelloWorld myClass; で、myClassという参照変数のメモリーを確保します。ここでは、まだ、参照変数はどこも参照していません。そして、 【図1】 ┏━━ メモリー領域 ━━━━━━━━━━━━━━━━━━━━━━
で、myClass参照変数が参照するメモリー領域を確保(図2の右側の箱、メモリーアドレス)し、myClassはその領域を参照(C,C++的にいえば、”指す(point)”)します。myClassが領域を参照するとは、myClass参照変数が、HelloWorldクラスのオブジェクトの、確保されたメモリーアドレス情報(メモリーアドレスそのもの)をその参照変数の中に保持するということです。 実生活で考えれば、メモリーアドレスは、住所に当たります。コンパイラーくんは、myClassさんの家を知りたいときに、あなたの家はどこですか?と、myClassさんに尋ねます。myClassさんは、東京のどこどこです、といえば、コンパイラーくんは、そこまでたどり着くことができます。コンパイラーくんはもう一度myClassさんに住所を訪ねます。すると、今度は、myClassさんは、引っ越したため、沖縄のどこどこです、と答えました。それでも、コンパイルくんは、住所がわかるためそこまでたどり着くことができます。この例で引っ越したとは、myClassが参照するアドレスが別のアドレスになったということを意味します。 参照されているメモリー領域(下記の図の右側の箱)は、オブジェクトを生成するクラス(仕様書)によって確保する大きさは異なります。例えば、クラス仕様書で、たい焼きであんこの他に、小倉あんを詰めるようにすれば、小倉あんを入れられるだけ大きくなってしまいます。チーズも詰めたらもっと大きくなりますね。一方で、myClassである参照変数は、HelloWorldで作られる参照変数であろうと、HelloWorldDemoで作られる参照変数であろうと、同じメモリーサイズ(32bits)です。なぜなら、myClassの参照変数の役割は、newで確保されたメモリーを参照する(指す)だけだからです。 【図2】 ┏━━ メモリー領域 ━━━━━━━━━━━━━━━━━━━━━━ ここではっとした方もいらっしゃるでしょう。そうJavaにもpointerという概念があるんです。C++と同じ参照という言葉を使っていますが、C++の場合は参照変数に変数を割り当てることができないなど、Javaの参照変数とは違うところがあります。Javaの参照変数はむしろ、C、C++のポインター(pointer)に近いです。Javaの場合、そのオブジェクトが誰からも参照されなくなったときに自動的にgarbage collectionされるので、C,C++であるようなfreeやdeleteをつかって確保したメモリーを解放してあげる必要はないのです。また、Javaはこの辺がオートマティックなのでメモリー確保、解放をつっこんでみたい方はC,C++を勉強してみてください。Javaに比べて配列に割り当てたメモリー以外のところにもアクセスできたりといろいろとC,C++のパワーを感じるところですが、その反面error proneな(エラーを含みやすい)ところもあるのは確かです。C,C++を勉強することによってまたJavaのいろいろな側面を再確認することができると思います。 もう一つおまけに、配列(Array)も参照変数です。例えば、 int[] integers = new int[10]; のintegersも参照変数なので、10個分ののint型タイプのメモリースペースが確保された場所をintegersが参照します。 Javaはメモリー確保なんて考えなくてもいいのさ。そこがJavaのいいところのなんだから。 まさにそうです。しかしながら、この概念を理解しているか否かによって、値渡し(passed by value)と、参照渡し(passed by reference)がわかり易くなるとおもいます。
ところで、SystemもHelloWorldもクラス名ですが、何でクラスだとわかったのでしょう?Javaにはネーミングのconvention(慣習)があります。クラス名には最初は大文字で表記し、各単語の最初の文字も大文字にします。たとえば、HelloWorldではHとWが大文字です。Javaはcase sensitive(大文字小文字を区別)なのでHelloWorldとhelloworldは区別されます。assempbly languageなどのように大文字小文字を区別しない言語を使っていた方は注意が必要です。 じゃー、メソッド(Method)は? メソッドは、最初の文字は小文字、それ以降の単語の最初の文字だけ大文字にします。C、C++を使っていた方、getmessageではなく、getMessageにしてくださいね。メソッドはメソッド名のあとに( )がついています。括弧の中にはString, int, dobuleなどのparameter(パラメータ、引数)が、はいる場合がありますが、メソッドには必ず( )がついています。ただ注意してもらいたいのは、”メソッドなら、カッコ有り”は正しいですが、”カッコ有りなら、メソッドである”は常に正しいとは限りません。というのは後で説明するコンストラクター(constructor)も同じカッコがあるからです。もっとも、コンストラクター名はクラスと同じにしなければならないので、メソッドは始まりは小文字、つづく単語の始まりは大文字、という慣習(convention)に従うなら、容易に区別できます。コンストラクターには、戻り値もない点も区別のポイントです。 メンバフィールド、つまり、インスタンス変数は? これも、メソッドと同じく、最初は小文字、それ以降の単語の最初の文字は大文字にします(例えば、 myVariable)。 クラスは最初の文字を大文字にしなくてもコンパイルできるんでしょ? そうです。しなくても大丈夫です。ためしに、ファイル名をhelloworld.javaでクラス名をhelloworldとして、コンパイルしてみてください。うまくったでしょ? それじゃー、ファイル名とクラス名を変えても大丈夫? 大丈夫です。試しにファイル名をhelloworld.java、クラス名をHelloWorldとしてコンパイルしてみてください。といいたいところですが、CPadを使ってするとエラーがでてしまいます。しかしながら、実際は可能です。HelloWorld.classが生成されます。そこで、Dos上からコンパイル、実行してみましょう。 CPadを立ち上げると、右端に実行と書いたブルーの四角いところがありますね?そこをクリックして、Dosプロンプト(Commandプロンプト)画面を立ち上げます。そのフォルダは、デフォルトで設定してある、標準データの保存フォルダが開くと思います。そこにあるファイルのうち、どれかのファイルネームを変えてください。たとえば、前回作った、HelloWorldDemo1.javaをhelloworlddemo1.javaと変えてください。それでは、実際にファイル名と名前の違うクラスを生成されるかどうか目で確かめて見ましょう。、まず、今現在存在するクラスファイルを削除します。今さっき開いたコマンドプロンプト上で del *.class を入力(delは削除コマンド(deleteの略))した後エンターキー(Enter)を押します。、拡張子がclass(たとえば、HelloWorldDemo1.class)を全て(*、アスタリスクを使って)消去します。確認のため、dirコマンド(ディレクトリを表示)をタイプし、 dir 次に、コンパイルするために、 javac helloworlddemo1.java とタイプします。javacはコンパイルするためのコマンドです。確認のため、dirをつかってフォルダを表示してみてください。 dir そうすると、クラスファイル、HelloWorld1.classが生成されていますね。どうです?ファイル名と違うクラスファイルが生成されたでしょ?そして最後に、 java HelloWorldDemo1 と入力しすると、Dosコマンド上に ハローワールドと表示されると思います。Dosプロンプト上でも簡単でしょ?でもそれ以上に、CPad上だともっと簡単だことがわかりますね。 ところで、今ちょこっとふれたJavaスタイルconventionは、後々『Javaスタイル職人への道(仮名)』でスタイルを紹介していきます。
本題に戻りますが、System.out.printlnの単語間にある点は .operater(ドット演算子)といって、日本語では"の”に当たります。たとえば、HelloWorld.getMethod()は、HelloWorldクラスのgetMethod()メソッドという意味です。System.out.println()ではどうでしょうか?。System.outは、Systemクラスのoutフィールドとよみます。その次の点は、outフィールドののprintln()メッソッドとよみます。おっと、これで本当にいいですか?outはSystemクラスのfieldでしたね。そのoutフィールドのprintln()メソッドって何ですか?これはおかしいですね。フィールドにメッソッドなんてありません。クラスにはメッソッドがありますが。正しくは、(System.out).println()です。つまり、(System.out)クラスのprintln()メソッドです。(System.out)ってなんのクラス?と思われた方、もう一度Java APIのSystemクラスに戻ってみてください。そこのoutの左側にはなんとかいてありました?左の列はは戻り値を示しています。static PrintStreamでしたね?staticは次回説明しますが、PrintStreamがクラス名です。つまり、戻り値はPrintStream型です。こう考えるととわかりやすいでしょう。 System.out.println("Hello World"); は PrintStream myOut = Sytem.out; と同じです。ドット演算子を用いてPrintStreamクラスのmyOutオブジェクトにprintln()メソッドを適用したことになります。つまり、println()メソッドは、PrintStreamクラスのメソッドという答えを導き出せます。
import java.io.*; /** ━━━━━━━━━━━━ ここまで ━━━━━━━━━━━━━━━━━━
System mySystem = new System(); とはできません。初期化(instantiatation)できないとは、mySystemをnewを使って作れないと言うことです。もっと専門的に言えば、コンストラクターのaccess modifier(アクセス指定)がprivateなのでSystemのクラスの外からアクセスできない、つまり、newを使ってインスタンスを生成できない、ということです。 ???んん??? 初心者の方は、そうおもったでしょ?でもいいんです。staticがついているときは、mySystemというようなオブジェクトを作らなくても、クラス名.メソッド名としてアクセスできると、今のうちは思っていてください。 ハローワールドプログラムでいろいろなことを学びましたね。来週からいよいよプログラムに入っていきます。そろそろ本腰を入れていきましょう。下記の問題にチャレンジしてみましょう。初心者の方から中級者の方まで、億劫がらず、実際に考えてプログラムしてみてくださいね。自分でまず、考えてみることが大切です。その想像力があとあと、威力を発揮します。
【Question 2-1】 前号vol.002の例であがっていたclassでコンパイルできないものはどれか? 【Question 2-2】
変換公式はCelsius = (fahrenheit - 32) * 5 / 9 で、メソッド定義として、double convertToCelsius(double fahrenheit)を使用せよ。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ヒント 2-1 皆さんは、前回ですでに発見できていましたか?もし、発見できなかったあなたは、なぜ、発見できなかったのでしょう? ヒント 2-2 あなたは、友達とアメリカに旅行に行ったと仮定してください。アメリカは気温には、華氏(F、ファランヘイト)を単位として使っています。友達がテレビを見みていると、天気予報で明日の気温は72Fといっています。これを華氏に直さないと友達はいったい何度なのかわかりせん。そこで、あなたは上記のプログラムを作ろうと決めました。 たとえば、あなたは、こんなユーザーインターフェイスを考えています。 華氏(Fahrenheit)を入力せよ:72 72を一行目で入れると二行目で華氏を自動的に表示します。 文字列をコマンドプロンプト上から得るには、 InputStreamReader inputStreamReader = new InputStreamReader(System.in); String型からdouble型へ変換するには、Doubleクラス参照。その中のあるメソッドで得ることができます。左のセルの戻り値のところにstaticがついていれば、Double.メソッド名で戻り値を得ることができます。 InputStreamReader BufferedReaderどこのパッケージ(package)ですか?java.ioですね。このパッケージをインポート(import)しないと上記のようにプログラムを書くことができません。 import java.io.*; class ConvertToCelsius1 { とクラスの上(外側)に記述しましょう。 少しずつ歯ごたえが出てきましたね。噛みがいがありますか?
それでは、またあいましょう。hava a good day. Mr.Hack ■ちょっと珈琲ブレイク いいんです。今は、これ見ただけで、何にも思い浮かばなくて。むしろ思い浮かんで完璧だっだら、このメルマガをそれこそ見る必要はないと思います。ど級初心者だと思ってるあなたも、Javaの文法習得が最終目標じゃありませんよね?英語の文法をたくさん知っているからと言って、どれだけお話ができますか?どれだけ、英作文ができますか?もちろん、Mr.Hackも文法は軽視しません。最初から全てをわかろうとして、わからなくて、先へ進まず、挫折してしまった人がいました。まさしく、Mr.Hackです。Mr.Hackも解決しないところがあると、なんか、もぞもぞして落ち着けない。本屋で立ち読みし、見つけられず、先へすすまず、ゲームオーバー。それに比べ、あなたはもう、次回で5回目の購読者です。それで、すでに、ちゃんとしたプログラムを完成させようとしています。ユーザーの目的をちゃんと達成できるプログラマーなのです。すごいことじゃないですか。文法が完全にわからなくても、外人と会話したのと同じことを意味すると思います。あきらめるな、がんばれ!超ど級初心者。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
||
© 2002 MR.HACK ALL RIGHTS RESERVED |