Object配列から汎用配列への変換の擬似ソリューション


暇で大丈夫で、現在のJava技術でオブジェクトデータベースをシミュレートしたいです.最初は単純な構想にとどまり、単一ユーザー、ローカル、単純なオブジェクト化されたデータベース操作を実現するためにすぎません.
 
public interface DataBase
{
    public <T> T[] select(Filter<T> filter);
    public <T> void insert(T t);
    public int update(Filter<T> filter, Updater<T> handler);
    public <T> int delete(T t);
}

 
 
ここで,FilterとUpdaterはそれぞれ2つのインタフェースであり,クエリ句と更新句を処理する.
 
public interface Filter<T>
{
	public boolean where(T obj);
}

public interface Updater<T>
{
	public void set(T obj);
}

 
 
このような設計の目的は、データをオブジェクト化して処理し、データベースの操作とビジネスプロセスをシームレスに結びつけることです.私が言ったように、これは私の練習にすぎないので、それだけを練習と見なしてください.データベースのオブジェクトコンテナには、任意のオブジェクトを含む汎用リストが使用されます.
 
しかしselect法では,いくつかの問題にぶつかった.T[]タイプの結果を返すため、Tが汎用であるため、ListのtoArrayではObject[]タイプの配列しか生成できず、需要とは異なる.
 
//...

@SuppressWarnings("unchecked")
public <T> T[] select(Filter<T> filter)
{
    Collection<T> c= new ArrayList<T>();
    for (Object obj : pool) {
        try {
            T t = (T) obj;
            if (filter.where(t)) c.add(t);
        } catch (Exception ex) {
            continue;
        }
    }
    //     OK
    return c.toArray(); //  OK,     Object[],     
    return (T[]) c.toArray(); //  OK,    Object[],ClassCastException
    return c.toArray(new T[0]); //  OK,    。
}

//...

 
まず、なぜreturn c.toArray(new T[0]);コンパイルできません.Java公式によると、旧バージョンへの互換性のため、Javaの汎用型はコンパイル期間にしか存在しないため、コンパイル期間のソースコードの正確性チェックを目的としている.class以降、すべての汎用コンテンツが捨てられました.したがって、new T[0]という書き方は、Tの具体的な定義がないため、運転期間中に意味があるはずがない.
 
@SuppressWarnings("unchecked")を追加した理由はT t=(T)objである.文.より良い方法で汎用的なタイプを比較するとは思わなかったが、この方法が最も直接的だ.ただしClassCastExceptionが発生する可能性があるので、変換エラーが発生すると、次の要素を簡単に処理し続けるだけです.他の解決策があれば教えてください.ここで謝ります.
 
今、問題に戻ります.どうやってこの汎用的な配列変換を実現しますか.
 
ここには偽の解決策があります.結果セットから値を取り出し、次のように値タイプの配列を作成します.
 
@SuppressWarnings("unchecked")
public <T> T[] select(Filter<T> filter)
{
    Collection<T> c;
//...
    Iterator<T> it = c.iterator();
    if (it.hasNext()) {
        T[] tt = (T[]) Array.newInstance(it.next().getClass(), c.size());
        return c.toArray(tt);
    } else return null;
}

 
 
これが擬似解である理由は,集合中の値がTに等しいわけではなく,Tのサブクラスである可能性があるからである.集合内のすべての要素が1つのカテゴリであるならまだしも、一部の要素がサブクラスの子(孫)であることを恐れている.たまたま集合の中で最初に手に入れたのが孫であると仮定すると、ttは実際には孫の配列であり、サブクラスオブジェクトを含む集合に対してtoArray操作を実行するとArrayStoreExceptionが現れる.
 
さて、この「偽」の字をしばらく考えない場合、ここで使用例を挙げます.
 
public static void main(String[] args)
{
    DataBase db = new DataBaseImpl();
    db.insert("Hello, ");
    db.insert(" this ");
    db.insert(new Integer(3));
    db.insert("world!");

    String[] ss = (db.select(new Filter<String>() {

        @Override
        public boolean where(String obj)
        {
            return (obj.trim().length() > 4);
        }

    }));

    for (String s : ss)
        System.out.println(s);
}

 
=====================補足
春節は休みで家にいて、たまにフォーラムを見ました.以下のコメントと結びつけて考えてみたが,現在は伝達されたFilterによって汎用クラスを得る方法が採用されている.
 
import java.lang.reflect.*;
import java.util.*;

public class Container {
    private Collection<Object> container = new ArrayList<Object>();

    public void add(Object obj) {
        container.add(obj);
    }

    @SuppressWarnings("unchecked")
    public <T> T[] select(Filter<T> filter)
    {
        Class clazz;
        Type[] types = filter.getClass().getGenericInterfaces();
        if (types != null && types.length > 0) {
            clazz = ((Class) ((ParameterizedType) types[0])
                    .getActualTypeArguments()[0]);
        } else return null;
        Collection<T> c = new ArrayList<T>();
        for (Object o : container) {
            if (clazz.isInstance(o) && filter.where((T) o))
                c.add((T) o);
        }
        T[] tt = (T[]) Array.newInstance(clazz, c.size());
        return c.toArray(tt);
    }

    public static void main(String[] args) {
        Container c = new Container();
        c.add("Hello");
        c.add("world");
        c.add("I");
        c.add("love");
        c.add("you");
        c.add(new Integer(4));
        c.add("ever");

        String[] list = c.select(new Filter<String>() {
            public boolean where(String s) {
                return (s.length() > 3);
            }
        });
        for (String s : list)
            System.out.println(s);
    }
}

interface Filter<T> {
	boolean where(T t);
}