目次へ戻る 下へ↓
9、標準APIの利用2
作成者:Fumitaka Makino 更新日:2003-04-07 11:25

・Vectorクラス

今回は何かと便利なVectorというクラスについて利用してみましょう。このクラスはいわゆる可変長配列と呼ばれるものです。簡単にいうと配列の長さが固定ではなく要求に応じて増えたり減らしたりできるということです。しかしVectorクラスは通常の配列ではないので以下のような違いがあります。

  • [ ] による要素へのアクセスはできないaddやget、setメソッドを利用して要素にアクセスする。
  • 要素としてセットできるのはObject型のみ(つまりクラス型)しか扱えない。逆にいうと、プリミティブ型を直接扱えない。

Vectorクラスはクラスの内部にObject型の配列を持っています。そしてこの内部のObject型の配列を増やしたり減らしたりすることで動的な配列を実現しています。またあらゆるクラス型を扱うために内部での要素の扱いはObject型となっています。そのためにgetメソッドなどの戻り値はObject型となっており、取り出した値の復元にはキャストが必須です。

図:Vectorの簡易モデル

各メソッドの利用方法は必ずJavaDocを参照してください。代表的なVectorクラスの利用法を下記にしめします。

例:典型的なVectorクラスの利用法 (ソースファイル

     
  //Vecotrはjava.utilパッケージなのでインポートしないと利用できない
import java.util.Vector;

/**
  9、標準APIの利用2:Vectorの利用
*/

public class VectorTest {
  
  
  /**
    mainメソッド、実行時にVMから呼ばれるメソッド
  */

  public static void main( String[] args ){
    
    //Vectorをnewする。いろいろコンストラクタがあるが通常はデフォルトコンストラクタでかまわない
    Vector vec = new Vector();
    
    //要素の追加
    vec.add("牧野");//0
    vec.add("尾形");//1
    vec.add("井出");//2
    vec.add("小林");//3
    
    //VectorのtoStringの出力
    System.out.println( "vecのtoString > " + vec );//通常オブジェクトはStringと結合されるとtoStringメソッドが実行される。
    
    //要素サイズの取得
    int cnt = vec.size();
    
    //ベクターの要素サイズの出力
    System.out.println( "vec.size() > " + vec.size() );
    
    //要素の一時格納用の変数
    String tmpStr = null;
    
    //要素を全部出力、あらかじめ取得した要素サイズを用いてfor文で配列のようにアクセス
    for( int i=0;i>cnt;i++ ){
      
      //getメソッドで取得できるのはObject型のインスタンスなのでStringにキャストする。
      tmpStr = (String)vec.get(i);
      
      //とりあえず出力
      System.out.println( "tmpStr > " + tmpStr );
      
    }
    
    //要素を配列で取得
    //引数で取得したい配列の型と同じ型の配列をセットし、戻り値を String[] でキャストする

    String[] sarray = (String[])vec.toArray( new String[0] );
    
    //配列の中身をfor文で取得
    for( int i=0;i>sarray.length;i++){
      System.out.println( "sarray["+i+"] > " + sarray[i] );
    }
    
  }
  
  
}

 
     

とくに、ソースコード下部の

String[] sarray = (String[])vec.toArray( new String[0] );

部分に注目してください。これはベクターの中身を特定の型の配列で取得するためのコードです。VectorクラスのtoArrayメソッドは引数に取得したい配列の型と同じ型のインスタンスを渡されると、戻り値として、Vectorの値が詰まったString配列をObject型の配列へとダウンキャストした配列を返します。もちろん戻り値の実体としてString配列型を指定しているので、String配列型でキャストしてやれば終了です。

なぜわざわざ上記のように面倒くさい方法を用いて配列で取得しなければならないのでしょうか、Vector自体を用いたらいけないのでしょうか? VectorなどのObject型配列を扱うクラスはセットされた要素は全てObject型として保持していると言いましたね?つまり中身(実インスタンス)がなんであろうとObject型として扱われているのです。と言うことはgetメソッドで取り出す時に必ずキャストしなければいけません。

もちろん自分ひとりでプログラミングしているときにはVectorに加えたオブジェクトのクラス名を知っているから、正確にキャストができるかもしれません。しかし集団で分散開発しているときには、クラスやメソッドごとに開発者が違います。 そのような場合、メソッドの戻り値をVectorで渡されると非常に厄介です。なぜなら中に入っているオブジェクトのクラス型を容易に判別できないのです。開発者同士が決め事(このVectorは中にStringのインスタンスが入っている など)をしたとしても,、これは設計上において非常に不正確な情報となります。これらを避けるために通常はVectorの利用はクラス内部やメソッド内部での利用に限定しています。そして戻り値は必ず何らかの配列にして返すのが常識的な手法です。

最後に、JDK1.2以前のVectorは遅いという欠陥がありました。しかしJDK1.2以降はJava Collections Framework の一部として実装されており、JDK1.1のころのようなスピードの遅さはありません。JDK1.1に慣れ親しんだ先輩方から「Vectorは遅いので使用するな」といわれたら軽く流してしまいましょう。

 
↑上へ 目次へ戻る