【Java備忘録】ラッパークラス、Collection(Set,List)、Map、配列の中身の自動判別

はじめに

外部I/F へ入出力する際、共通処理したい場合などに「Object型」をつかうことがありますよね。
ラッパークラス(Byte,Boolean,Integer,Long..)、Collecion、Set、List型や Map型 等のすべてのオブジェクトクラスの祖先である、曖昧な型です。 代表的なクラスの系譜は以下のとおりです。
たまに、メソッドの引数にモードやフラグを用意してそれを判断して、Object型をキャストするような処理を書いているソースコードを見かけることがあります。
「不要な引数は増やさない。」ここではそのために Object の型を判定する処理について説明します。

java.lang.Object
    ↳ java.util.Collection (インターフェース)
        ↳ java.util.List (インターフェース)
            ↳ java.util.ArrayList
            ↳ java.util.LinkedList
        ↳ java.util.Set (インターフェース)
            ↳ java.util.HashSet
            ↳ java.util.TreeSet
    ↳ java.util.Map (インターフェース)
        ↳ java.util.HashMap
        ↳ java.util.TreeMap
        ↳ java.util.LinkedHashMap

判別方法

オブジェクトがListなのか、Mapなのか、文字列なのか、数値型なのか、その他なのかを判別するのには、「instanceof」を使います。
「instanceof」は、そのクラスまたはそのクラスを基底(ルーツ)にもつクラスかどうか判定する演算子です。

// 前提: Object obj は メソッドの引数設定時に アップキャストされてきたもの
if ( obj instanceof List ) {
    // obj は List 型です
}
else if ( obj instanceof Collection ) {
    // obj は List 型ではない(=事前の判定による) Collection 型です
    // つまり、Set, HashSet, TreeSet などの集合体型です
}
else if( obj instanceof Map) {
    // obj は Map 型です
}

上記に付け加えて必要になる判定ですが、オブジェクトが配列かどうかの判別するには、java.lang.Class型 の「
isArray()」を使います。

if( obj.getClass().isArray() ) {
    // obj は 配列型です
}

最後に

紹介した方法で Object 型を判定することができるので、共通処理を作るのが便利。と思いますが、
必要以上に Object 型を使用しない ようにしてください。
冒頭で説明したとおり、このクラスは 曖昧 です。処理を呼び出す側次第で何色にでもなるので、リスクがあります。できる限りは 型を明確にするようにしましょう。


百聞は一見に如かず。お試しのソースを書いたので参考にして、自分のものにしてください。

お試しソース

import java.lang.reflect.Array;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.math.BigDecimal;

class objectTest {
    public static void main(String args[]) {
        //値のセット
        String[] strList = new String[] {"String1","String2","String3","String4","String5"};
        int[] intList = {2, 3, 5, 7, 9};
        char[] chrList = {'C', 'H', 'A', 'R'};
        List<Map<String,Object>> mapList1 = setTestData();
        List<Map<Integer,Object>> mapList2 = setTestData2();
        List<Object> mapList3 = setTestData3(mapList1, mapList2);
        //値の判定と出力
        anythingOutput(null);
        anythingOutput("test");
        anythingOutput(new BigDecimal(0.00003));
        anythingOutput(strList);
        anythingOutput(intList);
        anythingOutput(chrList);
        anythingOutput(mapList1);
        anythingOutput(mapList2);
        anythingOutput(mapList3);
    }
    /**
     * 型判定出力
     * @param obj オブジェクト型の値
     * @return テストデータリスト
     */
    private static void anythingOutput(Object obj) {
        anythingOutput(obj, 0);
    }
    /**
     * 型判定出力
     * @param obj オブジェクト型の値
     * @param intDept 階層
     */
    private static void anythingOutput(Object obj, int intDept) {
        System.out.print(blank(intDept));
        if(obj == null) {
            System.out.print("[null]");
        } else if(obj.getClass().isArray()) {
            //オブジェクトが配列の場合
            int len = Array.getLength(obj);
            System.out.print("[Array] value= {\n");
            for(int i=0; i < len; i++) {
                //配列の件数分、再帰的な処理を行う
                anythingOutput(Array.get(obj, i), intDept + 1);
            }
            System.out.print(blank(intDept) + "}");
        } else if(obj instanceof Collection<?>) {
            //オブジェクトがコレクション型の場合
            Collection<?> list = (Collection<?>)obj;
            System.out.print("[Collection] value= {\n");
            for(Object row : list) {
                //リストの件数分、再帰的な処理を行う
                anythingOutput(row, intDept + 1);
            }
            System.out.print(blank(intDept) + "}");
        } else {
            //オブジェクトがコレクション型でない場合
                if(obj instanceof Map) {
                    //Mapの場合
                    Map<?,?> map = (Map<?,?>) obj;
                    System.out.print("[Map] value={\n");
                    Iterator<?> keyItr = map.keySet().iterator();
                    Object key = null;
                    while(keyItr.hasNext()) {
                        //キーが取得できる場合、出力
                        key = keyItr.next();
                        anythingOutput(key, intDept + 1);
                        System.out.print(blank(intDept + 1) + " : ");
                        anythingOutput(map.get(key), 0);
                    }
                    System.out.print(blank(intDept) + "}");
                } else if(obj instanceof String) {
                    //文字列の場合
                    System.out.print("["+ obj.getClass().getName() +"] value=\"" + (String)obj + "\"");
                } else if(obj instanceof Number) {
                    //数値の場合
                    System.out.print("["+ obj.getClass().getName() +"] value=\"" + ((Number)obj).toString() + "\"");
                } else {
                    //その他の場合(toStringはObjectのメソッド)
                    System.out.print("["+ obj.getClass().getName() +"] value=\"" + obj.toString() + "\"");
                }
        }
        System.out.print("\n");
        return;
    }
    /**
     * テストデータの設定
     * @return テストデータリスト
     */
    public static List<Map<String,Object>> setTestData() {
        //オブジェクトの初期化
        List<Map<String,Object>> mapList = new ArrayList<Map<String,Object>>();
        Map<String, Object> map = null;
        //10件分のテストデータを作成する
        for(int i = 0; i < 10; i++) {
            map = new HashMap<String, Object>();
            //キー名(String)、キー値(Integer)
            map.put("keyCd", Long.valueOf(i + 1));
            //属性名(String)、属性値(String)
            map.put("text", (new String(Character.toChars(65+i)).concat(String.valueOf(i+1))) );
            mapList.add(map);
        }
        return mapList;
    }
    /**
     * テストデータの設定
     * @return テストデータリスト2
     */
    public static List<Map<Integer, Object>> setTestData2() {
        //オブジェクトの初期化
        List<Map<Integer,Object>> mapList = new ArrayList<Map<Integer,Object>>();
        Map<Integer, Object> map = null;
        //10件分のテストデータを作成する
        for(int i = 0; i < 10; i++) {
            map = new HashMap<Integer, Object>();
            map.put(Integer.valueOf(1), (i + 1));
            map.put(Integer.valueOf(2), (new String(Character.toChars(65+i)).concat(String.valueOf(i+1))) );
            mapList.add(map);
        }
        return mapList;
    }
    /**
     * テストデータの設定
     * @return テストデータリスト3(Listの子にListがある)
     */
    public static List<Object> setTestData3(Object objList1, Object objList2) {
        //オブジェクトのマージ
        List<Object> newList = new ArrayList<Object>();
        newList.add(objList1);
        newList.add(objList2);
        newList.add("test3");
        newList.add(Long.valueOf(4));
        newList.add(null);
        return newList;
    }
    /**
     * 空白文字返却
     * @param 空白文字繰り返し回数
     * @return 空白文字列
     */
    private static String blank(int intRepeat) {
        String strBlank = "";
        for(int i = 0; i < intRepeat; i++) {
            strBlank = strBlank.concat(" ");
        }
        return strBlank;
    }
}
タイトルとURLをコピーしました