広告

■□■□■□■□■□■□■□■□■□■□■□■□■□■□■
                      2010年02月10日

    Java総合講座 - 初心者から達人へのパスポート
                  2009年11月開講コース 013号

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■□■□■□■□■□■□■□■□■□■□■□■□■□■□■


-------------------------------------------------------
・現在、このメールマガジンは以下の2部構成になっています。
[1] 当初からのコース:毎週日曜の夜に発行
   これは現在、中級レベルになっています。
[2] 2009年11月開講コース:毎週水曜の夜に発行
   これは現在、初心者向けのレベルになっています。
・このメールマガジンは、画面を最大化して見てください。
小さな画面で見ていると、不適切な位置で行が切れてしまう
など、問題を起すことがあります。
・このメールマガジンに掲載されているソース・コード及び
文章は特に断らない限り、すべて筆者が著作権を所有してい
ます。また、これらのソース・コードは学習用のためだけに
提供しているものです。
-------------------------------------------------------


━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
(2009年11月開講コース)013号
 当記事はvol.013のリバイバル(revival)版です。
 vol.013の内容を最新のEclipse、Javaに基づいて書き直しています。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


========================================================
◆ 01.和暦を西暦に変換するクラス(続き)
========================================================

前回はCalendarConverterクラスにconvertGreCal2JaCal()のメソッド
を追加し、CalendarConverterWindowクラスを改良しました。

念のため、CalendarConverterクラスの全ソース・コードを下に掲載
します。

-------------------------------------------------------
package jp.co.flsi.lecture.util;

public class CalendarConverter {
   private int jaNameOfEra;  // 0 = 明治, 1 = 大正, 2 = 昭和, 3 = 平成
   private int jaYear;  // Japanese Calendar
   private int greYear;  // Gregorian Calendar
   private int Month;
   private int Day;
   public void setJaNameOfEra(int jaNameOfEra) {
      this.jaNameOfEra = jaNameOfEra;
   }
   public int getJaNameOfEra() {
      return jaNameOfEra;
   }
   public void setJaYear(int jaYear) {
      this.jaYear = jaYear;
   }
   public int getJaYear() {
      return jaYear;
   }
   public void setGreYear(int greYear) {
      this.greYear = greYear;
   }
   public int getGreYear() {
      return greYear;
   }
   public void setMonth(int month) {
      Month = month;
   }
   public int getMonth() {
      return Month;
   }
   public void setDay(int day) {
      Day = day;
   }
   public int getDay() {
      return Day;
   }
   public void convertJaCal2GreCal() {
      switch (getJaNameOfEra()) {
      case 0:
         setGreYear(getJaYear() + 1867);
         break;
      case 1:
         setGreYear(getJaYear() + 1911);
         break;
      case 2:
         setGreYear(getJaYear() + 1925);
         break;
      case 3:
         setGreYear(getJaYear() + 1988);
         break;
      default:
         setGreYear(0);
      break;
      }
   }
   public void convertGreCal2JaCal() {
      if (1989 < getGreYear() || 1989 == getGreYear() && ((1 == getMonth() && 8 <= getDay()) || 1 < getMonth())) {
         setJaNameOfEra(3);
         setJaYear(getGreYear() - 1988);
      }
      else if (1926 < getGreYear() || 1926 == getGreYear() && ((12 == getMonth() && 25 <= getDay()))) {
         setJaNameOfEra(2);
         setJaYear(getGreYear() - 1925);
      }
      else if (1912 < getGreYear() || 1912 == getGreYear() && ((7 == getMonth() && 30 <= getDay()) || 7 < getMonth())) {
         setJaNameOfEra(1);
         setJaYear(getGreYear() - 1911);
      }
      else if (1868 < getGreYear() || 1868 == getGreYear() && ((9 == getMonth() && 8 <= getDay()) || 9 < getMonth())) {
         setJaNameOfEra(0);
         setJaYear(getGreYear() - 1867);
      }
   }
}
-------------------------------------------------------


また、CalendarConverterWindowクラスを改良したものは、下記の
ようになっていました。

改良点は、CalendarConverterクラスのconvertGreCal2JaCal()メソッ
ドを呼び出して西暦から和暦への変換を行えるようにしたことです。

-------------------------------------------------------
package jp.co.flsi.lecture.ui;

import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import jp.co.flsi.lecture.util.CalendarConverter;

public class CalendarConverterWindow extends Frame {
   private CalendarEventListener eventListener = new CalendarEventListener();
   private CalendarActionListener actionListener = new CalendarActionListener();
   private Label labelJaCalendar = new Label();
   private Panel ckboxPanel = new Panel();
   private CheckboxGroup nameOfEraCkboxGroup = new CheckboxGroup();
   private Checkbox checkboxMeiji = new Checkbox("明治", getNameOfEraCkboxGroup(), false);
   private Checkbox checkboxTaisho = new Checkbox("大正", getNameOfEraCkboxGroup(), false);
   private Checkbox checkboxShowa = new Checkbox("昭和", getNameOfEraCkboxGroup(), true);
   private Checkbox checkboxHeisei = new Checkbox("平成", getNameOfEraCkboxGroup(), false);
   private Label labelJaYear = new Label();
   private Label labelJaMonth = new Label();
   private Label labelJaDay = new Label();
   private Label labelGreCalendar = new Label();
   private Label labelGreYear = new Label();
   private Label labelGreMonth = new Label();
   private Label labelGreDay = new Label();
   private Button convertJa2GreButton = new Button();
   private Button convertGre2JaButton = new Button();
   private TextField textFieldJaYear = new TextField();
   private TextField textFieldJaMonth = new TextField();
   private TextField textFieldJaDay = new TextField();
   private TextField textFieldGreYear = new TextField();
   private TextField textFieldGreMonth = new TextField();
   private TextField textFieldGreDay = new TextField();
  
   class CalendarEventListener implements WindowListener {
      public void windowActivated(WindowEvent e) {};
      public void windowClosed(WindowEvent e) {
         System.exit(0);
      };
      public void windowClosing(WindowEvent e) {
         Frame frame = (Frame)e.getSource();
         frame.setVisible(false);
         frame.dispose();
      };
      public void windowDeactivated(WindowEvent e) {};
      public void windowDeiconified(WindowEvent e) {};
      public void windowIconified(WindowEvent e) {};
      public void windowOpened(WindowEvent e) {};
   };
  
   class CalendarActionListener implements ActionListener {
      public void actionPerformed(ActionEvent e) {
         Button button = (Button)e.getSource();
         CalendarConverterWindow window = (CalendarConverterWindow)button.getParent();
         CalendarConverter calendarConverter = new CalendarConverter();
         if (button.getLabel().equals("和暦から西暦へ変換")){
            if (window.getNameOfEraCkboxGroup().getSelectedCheckbox().getLabel().equals("明治")) calendarConverter.setJaNameOfEra(0);
            else if (window.getNameOfEraCkboxGroup().getSelectedCheckbox().getLabel().equals("大正")) calendarConverter.setJaNameOfEra(1);
            else if (window.getNameOfEraCkboxGroup().getSelectedCheckbox().getLabel().equals("昭和")) calendarConverter.setJaNameOfEra(2);
            else if (window.getNameOfEraCkboxGroup().getSelectedCheckbox().getLabel().equals("平成")) calendarConverter.setJaNameOfEra(3);
            calendarConverter.setJaYear(Integer.parseInt(window.getTextFieldJaYear().getText()));
            calendarConverter.setMonth(Integer.parseInt(window.getTextFieldJaMonth().getText()));
            calendarConverter.setDay(Integer.parseInt(window.getTextFieldJaDay().getText()));
            calendarConverter.convertJaCal2GreCal();
            window.getTextFieldGreYear().setText(Integer.toString(calendarConverter.getGreYear()));
            window.getTextFieldGreMonth().setText(Integer.toString(calendarConverter.getMonth()));
            window.getTextFieldGreDay().setText(Integer.toString(calendarConverter.getDay()));
         }
         else {
            calendarConverter.setGreYear(Integer.parseInt(window.getTextFieldGreYear().getText()));
            calendarConverter.setMonth(Integer.parseInt(window.getTextFieldGreMonth().getText()));
            calendarConverter.setDay(Integer.parseInt(window.getTextFieldGreDay().getText()));
            calendarConverter.convertGreCal2JaCal();
            if (calendarConverter.getJaNameOfEra() == 0) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxMeiji) ;
            else if (calendarConverter.getJaNameOfEra() == 1) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxTaisho) ;
            else if (calendarConverter.getJaNameOfEra() == 2) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxShowa) ;
            else if (calendarConverter.getJaNameOfEra() == 3) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxHeisei) ;
            window.getTextFieldJaYear().setText(Integer.toString(calendarConverter.getJaYear()));
            window.getTextFieldJaMonth().setText(Integer.toString(calendarConverter.getMonth()));
            window.getTextFieldJaDay().setText(Integer.toString(calendarConverter.getDay()));
         }
      };
   };
  
   public CalendarConverterWindow()  {
      super();
      setTitle("和暦西暦変換");
      setSize(400, 150);
      setLayout(null);
      labelJaCalendar.setBounds(10, 30, 200, 20);
      ckboxPanel.setLayout(new GridLayout(1,4));
      ckboxPanel.add(checkboxMeiji);
      ckboxPanel.add(checkboxTaisho);
      ckboxPanel.add(checkboxShowa);
      ckboxPanel.add(checkboxHeisei);
      ckboxPanel.setBounds(45, 60, 180, 20);
      getTextFieldJaYear().setBounds(230, 60, 20, 20);
      labelJaYear.setBounds(255, 60, 20, 20);
      getTextFieldJaMonth().setBounds(290, 60, 20, 20);
      labelJaMonth.setBounds(315, 60, 20, 20);
      getTextFieldJaDay().setBounds(350, 60, 20, 20);
      labelJaDay.setBounds(375, 60, 20, 20);
      convertJa2GreButton.setBounds(220,90, 160, 20);
      convertGre2JaButton.setBounds(20,90, 160, 20);
      labelGreCalendar.setBounds(10, 120, 200, 20);
      getTextFieldGreYear().setBounds(210, 120, 40, 20);
      labelGreYear.setBounds(255, 120, 20, 20);
      getTextFieldGreMonth().setBounds(290, 120, 20, 20);
      labelGreMonth.setBounds(315, 120, 20, 20);
      getTextFieldGreDay().setBounds(350, 120, 20, 20);
      labelGreDay.setBounds(375, 120, 20, 20);
      add(labelJaCalendar);
      add(ckboxPanel);
      add(getTextFieldJaYear());
      add(labelJaYear);
      add(getTextFieldJaMonth());
      add(labelJaMonth);
      add(getTextFieldJaDay());
      add(labelJaDay);
      add(convertJa2GreButton);
      add(convertGre2JaButton);
      add(labelGreCalendar);
      add(getTextFieldGreYear());
      add(labelGreYear);
      add(getTextFieldGreMonth());
      add(labelGreMonth);
      add(getTextFieldGreDay());
      add(labelGreDay);
      labelJaCalendar.setText("和暦:");
      labelJaYear.setText("年");
      labelJaMonth.setText("月");
      labelJaDay.setText("日");
      convertJa2GreButton.setLabel("和暦から西暦へ変換");
      convertGre2JaButton.setLabel("西暦から和暦へ変換");
      labelGreCalendar.setText("西暦:");
      labelGreYear.setText("年");
      labelGreMonth.setText("月");
      labelGreDay.setText("日");
      convertJa2GreButton.addActionListener(actionListener);
      convertGre2JaButton.addActionListener(actionListener);
      addWindowListener(eventListener);
      setVisible(true);
   }

   public CheckboxGroup getNameOfEraCkboxGroup() {
      return nameOfEraCkboxGroup;
   }

   public TextField getTextFieldJaYear() {
      return textFieldJaYear;
   }

   public TextField getTextFieldJaMonth() {
      return textFieldJaMonth;
   }

   public TextField getTextFieldJaDay() {
      return textFieldJaDay;
   }

   public TextField getTextFieldGreYear() {
      return textFieldGreYear;
   }

   public TextField getTextFieldGreMonth() {
      return textFieldGreMonth;
   }

   public TextField getTextFieldGreDay() {
      return textFieldGreDay;
   }

   public static void main(String[] args) {
      CalendarConverterWindow frame = new CalendarConverterWindow();
   }

}
-------------------------------------------------------

それでは、どのような改良を行ったのかを説明しましょう。

まず、以下の2つの作業内容を頭に入れた上でソース・コードを見てみ
ましょう。

(1) 「西暦から和暦へ変換」するためのボタンを設置する。
(2) そのボタンをクリックしたときのイベントをアクション・リスナーが
    受け取り、ウインドウ上のテキスト・フィールドから西暦のデータを
    読み取ってCalendarConverterに和暦へ変換させ、その変換結果をウイン
    ドウ上の和暦のテキスト・フィールドに書き出すようにロジックを組む。


まず(1)のほうは、以下のコードによってプログラミングされています。


36行目

private Button convertGre2JaButton = new Button();

(「西暦から和暦へ変換」ボタン用にButtonのオブジェクト(インスタンス)
を生成し、convertGre2JaButtonという変数に代入しています。)


113行目

convertGre2JaButton.setBounds(20,90, 160, 20);

(そのButtonオブジェクトを、(ウインドウの左上端から)右方向に20ピク
セル、下方向に90ピクセルの位置から幅160ピクセル、高さ20ピクセルの大き
さで配置されるように位置決めを設定します。)


130行目

add(convertGre2JaButton);

(そのButtonオブジェクトをウインドウに貼り付け(add(=追加)という言い方
をする)ます。)


143行目

convertGre2JaButton.setLabel("西暦から和暦へ変換");

(そのButtonオブジェクトのラベル(ボタンの表面に書かれる文字列)を
「西暦から和暦へ変換」に設定します。)


なお、この「西暦から和暦へ変換」ボタンを置く場所をあけるために、以前
から存在する「和暦から西暦へ変換」ボタンのほうは以前より位置を右にずら
しています。そのために


112行目

convertJa2GreButton.setBounds(220,90, 160, 20);

のコードの数値が以前と異なっています。


次に(2)のほうですが、以下のコードによって記述されています。


149行目

convertGre2JaButton.addActionListener(actionListener);

(「西暦から和暦へ変換」ボタンにアクション・リスナーを登録します。)


このアクション・リスナーは「和暦から西暦へ変換」ボタンにも登録されて
いる(148行目)ことを思い出してください。

つまり、このアクション・リスナーは「和暦から西暦へ変換」ボタンと
「西暦から和暦へ変換」ボタンのどちらのボタンからもイベントの情報を
受け取ることになります。


65行目から90行目

if (button.getLabel().equals("和暦から西暦へ変換")){
   ・
   ・
   ・
}
else {
   calendarConverter.setGreYear(Integer.parseInt(window.getTextFieldGreYear().getText()));
   calendarConverter.setMonth(Integer.parseInt(window.getTextFieldGreMonth().getText()));
   calendarConverter.setDay(Integer.parseInt(window.getTextFieldGreDay().getText()));
   calendarConverter.convertGreCal2JaCal();
   if (calendarConverter.getJaNameOfEra() == 0) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxMeiji) ;
   else if (calendarConverter.getJaNameOfEra() == 1) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxTaisho) ;
   else if (calendarConverter.getJaNameOfEra() == 2) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxShowa) ;
   else if (calendarConverter.getJaNameOfEra() == 3) window.getNameOfEraCkboxGroup().setSelectedCheckbox(window.checkboxHeisei) ;
   window.getTextFieldJaYear().setText(Integer.toString(calendarConverter.getJaYear()));
   window.getTextFieldJaMonth().setText(Integer.toString(calendarConverter.getMonth()));
   window.getTextFieldJaDay().setText(Integer.toString(calendarConverter.getDay()));
}

66行目から76行目までのコードは以前からありましたが、これは
「和暦から西暦へ変換」ボタンがクリックされたときに実行される
ものとして用意されたものです。
以前は「和暦から西暦へ変換」ボタンしかありませんでしたから、
どのボタンがクリックされたのかを調べる必要などありませんでした。

ところが、今回は「和暦から西暦へ変換」ボタンと「西暦から和暦へ変換」
ボタンの2つのボタンが存在しますので、クリックされたのが
「和暦から西暦へ変換」ボタンのほうであることを確認してから実行する
必要があります。そのために65行目のif文

if (button.getLabel().equals("和暦から西暦へ変換")){

を追加することによって、buttonのラベル(ButtonクラスのgetLabel()メソ
ッドで取り出せる)が「和暦から西暦へ変換」という文字列になっている
(equals()メソッドで調べることができる)ことを確認しているのです。

┌補足─────────────────────────┐
button.getLabel().equals("和暦から西暦へ変換")
は、ButtonのgetLabel()メソッドがString型の戻り値を返すので、
Stringのequals()メソッドを呼び出すことになります。

このequals()メソッドは、そのStringオブジェクトの文字列と
引数に指定した文字列が等しいかどうかを調べ、等しければ
true(真)を、等しくなければfalse(偽)を返すものです。

button.getLabel().equals("和暦から西暦へ変換")
の代わりに
button.getLabel() == "和暦から西暦へ変換"
としても同じではないか、と思われるかもしれませんが、違い
ます。

button.getLabel() == "和暦から西暦へ変換"
とした場合は、button.getLabel()が返すStringオブジェクト(イン
スタンス)と"和暦から西暦へ変換"(これもJavaコンパイラーによっ
てString型のインスタンスにされる)とを比較して、同一のイン
スタンスであるかどうかが判断されます。

そうすると、インスタンスの中にはいっている文字列のデータ
が同じであってもbutton.getLabel()の戻り値のインスタンスと
"和暦から西暦へ変換"がインスタンス化されたものは別物です
から、結果がfalseになってしまいます。

というわけで、ここでは
button.getLabel() == "和暦から西暦へ変換"
を使うわけにはいかないのです。

このようにプリミティブ型ではなく、参照型(オブジェクト)の
持つデータが等しいかどうかを判定したい場合は、==ではなく、
equals()メソッドを使うということに注意してください。
└───────────────────────────┘

このif文の( )の中が真でない場合、つまりbuttonのラベルが
「和暦から西暦へ変換」という文字列になっていない場合は、78行目
のelse文によって79行目から89行目までが実行されることになります。

このときは「西暦から和暦へ変換」ボタンのほうがクリックされたことに
なりますから、西暦から和暦へ変換するための作業を行うことになります。

まず79行目から81行目まででやっていることは、もうおわかりでしょう。
ウインドウに入力された西暦の年月日のデータを取り出して、それらを
いったん文字から数に変換した後、CalendarConverterオブジェクトの
フィールド(属性を表す変数)に設定していますね。

続いて82行目の

 calendarConverter.convertGreCal2JaCal();

によって、CalendarConverterオブジェクトに西暦から和暦への変換を
行わせています。

83行目から86行目では、CalendarConverterオブジェクトの年号の属性
(jaNameOfEra)が明治(0)のときと大正(1)のときと昭和(2)のとき
と平成(3)のときとで振り分けて、それぞれのラジオ・ボタンを選択状態
にするように設定を行っています。ラジオ・ボタンの選択は、CheckboxGroup
オブジェクトのsetSelectedCheckbox( )メソッドによって設定できます。

setSelectedCheckbox( )メソッドの引数には選択状態にしたいCheckboxオブ
ジェクトを指定します。

87行目から89行目まででやっていることも、もうおわかりでしょう。
CalendarConverterオブジェクトによって変換された年と月日を数から文字列
に変換した後、それぞれウインドウ上のテキスト・フィールドに書き出して
いますね。



では、次にこのCalendarConverterオブジェクトを使って、以前のHumanWindow
を改良し、和暦の生年月日を入力しても年齢を計算してくれるようにしてみた
いと思いますが、その前に、ちょっと注意しておきたいことがあります。

これまで、HumanやCalendarConverterをウインドウで使用するときに、アクショ
ン・リスナーのメソッドの中でインスタンス生成をしていました。

このやり方は、ソース・コードは簡単そうに見えるのですが、効率のいい方法では
ありません。

これでは、ボタンをクリックするたびに毎回インスタンスが生成されることになり、
また、アクション・リスナーのメソッドの実行が終わるたびにインスタンスが消滅
させられることになります。
そして、このオブジェクトの生成・消滅のときには、若干コンピューター資源
(resource)(メモリーやCPU)に負荷がかかります。

このことは、現在作っている簡単なアプリケーションでは問題にはなりませんが、
本格的な大規模のシステム開発などでは問題になることがあります。

┌補足─────────────────────────┐
以前にもお話したように、ブロック({から}までの間)の中で
宣言された変数はブロック内でしか有効ではありません。
メソッドの中も同じくブロックになっており(メソッドもやはり
{と}で囲まれている)、この中で宣言された変数はメソッドの
実行が終わると消えて無くなってしまいます。

オブジェクトは変数自身ではありませんが、オブジェクトを参照
している変数(オブジェクトを代入した変数。この変数にはオブ
ジェクトのアドレスがはいっている)が消えてしまうと、オブ
ジェクトがどこからも参照されなくなってしまいますので、以前
お話したガーベジ・コレクションの機能によって、オブジェクト
も消滅させられます。
└───────────────────────────┘

こんなやり方をするよりも、インスタンスを一度生成したら、それをずっと使い
続けたほうがコンピューターに無駄な負荷がかからなくて済みます。

したがって、アプリケーションの起動時に一度インスタンスを生成し、その後、
その同じインスタンスを最後まで使い続けるというやり方がいいと考えられます。
これは、コンストラクターなどの中でインスタンスを生成するコードを書くことに
よって実装できます。

しかし、その場合、さらに考えてみると、インスタンスを一切使わずに終わって
しまうことも考えられるわけです(たとえば、アプリケーションの使用者によっ
ては生年月日をすべて西暦で入力する人もいるでしょう。このようなときには
CalendarConverterを使って和暦を西暦に変換をする必要もないわけで、
CalendarConverterのインスタンスを生成する必要がなくなります)。

そうすると、これらのインスタンスは必要になるまで生成せず、必要になった時点
で生成し、いったん生成したら、それを消滅させずにずっと使い続ける、というや
り方が望ましいと考えられます。


そのプログラミングの仕方をご紹介しましょう。このやり方は遅延生成
(lazy instantiation) と呼ばれており、よく使用されるテクニックの一つ
です。

たとえばCalendarConverterWindowの中で、CalendarConverterのオブジェクト
(インスタンス)を遅延生成させるようにプログラミングを修正してみましょう。

まず、CalendarConverterWindowにCalendarConverterのフィールド(属性を表す
変数)を用意します。

private CalendarConverter calendarConverter = null;

ここで、nullというのは「空っぽ」という意味をもつキーワードで、これを変数
に代入するとその変数は値が設定されていない空っぽの状態を意味することにな
ります。
上記の文では、calendarConverterはCalendarConverter型の変数として宣言されて
いますから、CalendarConverterクラスのインスタンスを代入するための変数という
ことになりますが、CalendarConverterクラスのインスタンスを代入すると、実際に
はインスタンスのアドレスがはいることになります。
この変数が何も代入されていない初期状態のときに、たまたま変数の記憶域として
確保されたメモリー上の場所にゴミのデータが残っていると、それをアドレスとし
て誤解して読み取ってしまう恐れがあります。しかし、nullがはいっていると、ア
ドレスが代入されていないことが明白になるのです。というわけで、上記の文のよ
うに初期値としてnullを代入しておくわけです。

そして、そのフィールドに対して、次のようなgetメソッドを用意します。

public CalendarConverter getCalendarConverter( ) {
   if (calendarConverter == null) calendarConverter = new CalendarConverter();
   return calendarConverter;
}

こうしておけば、getCalendarConverter()メソッドでcalendarConverterインスタンス
を取り出そうとすると、初回にはインスタンスが存在しない(calendarConverter変数
の値はnull)であるから、インスタンスを生成し、初回でないときは、生成せずに既
に存在するインスタンスを取り出すことになります。(なお、calendarConverter変数
は、このメソッドの外で宣言されているので、このメソッドが終了しても消え去るこ
とはありません。したがって代入されたCalendarConverterのインスタンスもこのメ
ソッドが終了しても削除されることはありません。)

そして、アクション・リスナーのメソッドの中では、CalendarConverterのインスタン
スを生成していた部分

CalendarConverter calendarConverter = new CalendarConverter();

を次のように書き換えます。

CalendarConverter calendarConverter = window.getCalendarConverter();

これだけで遅延生成のプログラミングは終わりです。
簡単ですね。

でも、この遅延生成のテクニックを嫌う技術者もいるんです。
なぜならば、getメソッドの中でインスタンス生成するなんて、get(取り出す)と
いうメソッド名の意味と合わないからです。

でも、効率のよいテクニックですから、皆さんは大いに利用しましょう。


はい、今日はこの辺で終わりにします。


次回は、この遅延生成を使いながら、和暦から年齢計算をできるようにHumanWindowを
拡張していきます。

その後、簡単なゲーム・プログラムの開発やアプレットの開発、ファイルへの読み
書き、データベース処理、Servlet, JSP, SOAP, EJBといったサーバー側のプログラ
ミング開発のお話といった順番で段々と本格的なプログラミングへと話を拡大して
いきます。なお、それに合わせて、さまざまなオープン・ソースの使い方も説明し
ていきます。

また、Eclipseのプラグインもいくつかインストールして機能アップしていくことに
なります。

もちろん、実際に使えるサンプルを豊富に提供しながら、お話を進めて行きます。

「まなぶ」は「まねる」という言葉が語源である、とはよく言われることですが、
プログラミングを学ぶときにもサンプルをまねることが有効です。

どんなに優秀なプログラマーも、最初は、まねることから始めているのです。



================================================
◆ 02.演習問題
================================================

上記の遅延生成を使ったCalendarConverterWindowの修正を、実際にEclipseに入力
して、実行しなさい。



======================================================
◆ 03.前回の演習問題の答
======================================================

今回の本文中に解答が含まれています。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2010 Future Lifestyle Inc. 不許無断複製