Object配列から汎用配列への変換の擬似ソリューション
暇で大丈夫で、現在のJava技術でオブジェクトデータベースをシミュレートしたいです.最初は単純な構想にとどまり、単一ユーザー、ローカル、単純なオブジェクト化されたデータベース操作を実現するためにすぎません.
ここで,FilterとUpdaterはそれぞれ2つのインタフェースであり,クエリ句と更新句を処理する.
このような設計の目的は、データをオブジェクト化して処理し、データベースの操作とビジネスプロセスをシームレスに結びつけることです.私が言ったように、これは私の練習にすぎないので、それだけを練習と見なしてください.データベースのオブジェクトコンテナには、任意のオブジェクトを含む汎用リストが使用されます.
しかしselect法では,いくつかの問題にぶつかった.T[]タイプの結果を返すため、Tが汎用であるため、ListのtoArrayではObject[]タイプの配列しか生成できず、需要とは異なる.
まず、なぜreturn c.toArray(new T[0]);コンパイルできません.Java公式によると、旧バージョンへの互換性のため、Javaの汎用型はコンパイル期間にしか存在しないため、コンパイル期間のソースコードの正確性チェックを目的としている.class以降、すべての汎用コンテンツが捨てられました.したがって、new T[0]という書き方は、Tの具体的な定義がないため、運転期間中に意味があるはずがない.
@SuppressWarnings("unchecked")を追加した理由はT t=(T)objである.文.より良い方法で汎用的なタイプを比較するとは思わなかったが、この方法が最も直接的だ.ただしClassCastExceptionが発生する可能性があるので、変換エラーが発生すると、次の要素を簡単に処理し続けるだけです.他の解決策があれば教えてください.ここで謝ります.
今、問題に戻ります.どうやってこの汎用的な配列変換を実現しますか.
ここには偽の解決策があります.結果セットから値を取り出し、次のように値タイプの配列を作成します.
これが擬似解である理由は,集合中の値がTに等しいわけではなく,Tのサブクラスである可能性があるからである.集合内のすべての要素が1つのカテゴリであるならまだしも、一部の要素がサブクラスの子(孫)であることを恐れている.たまたま集合の中で最初に手に入れたのが孫であると仮定すると、ttは実際には孫の配列であり、サブクラスオブジェクトを含む集合に対してtoArray操作を実行するとArrayStoreExceptionが現れる.
さて、この「偽」の字をしばらく考えない場合、ここで使用例を挙げます.
=====================補足
春節は休みで家にいて、たまにフォーラムを見ました.以下のコメントと結びつけて考えてみたが,現在は伝達されたFilterによって汎用クラスを得る方法が採用されている.
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);
}