3

私はこのように見えるいくつかのオブジェクトを持っています:

class PhoneNumber
{
   String   getNumber();
   String   getExtension();
   DateTime getLastCalled();
}
class Address
{
   String getCity();
   string getState();
   int    getZip();
}

これらのオブジェクトのいずれかのリストを取得して、特定のプロパティのリストを取得できるようにしたいと思います。プロパティごとに関数を作成する場合、これは簡単な操作ですが、理解しているように、コードを何度も複製することはお勧めできません。

したがって、どちらのオブジェクトの任意のプロパティに対しても、次のようなことができるようにしたいと思います。

List<Address> AddressList = getAddresses();
List<String> CityList = getListOfProperties( AddressList, Address.getCity /*<--Instruction as to what property to populate the returned list with */ )

私はジェネリックでこれをやろうとして頭を悩ませてきました。これが可能かどうかさえわかりませんが、私が理解しているように、Javaプログラミング言語を使用すると多くの魔法のようなことができます。

4

5 に答える 5

2

これほど単純なものについては、ゲッターとセッターを提供する方がよいでしょう。1行のコードの複製を拒否しても、それほど節約にはなりません。さらに良いことに、IDEにそれを書いてもらうだけです。

于 2010-02-03T20:15:27.157 に答える
2

この SO answerIntrospectorのようにオブジェクトを処理できます。

public <T > List<T > getMemberList( List<? > beanList, 
        String propertyName, Class<T > resultClass ) throws Exception {
    List<T > result = new ArrayList<T >();
    for( Object bean : beanList ) {
        result.add( (T )new PropertyDescriptor( 
                propertyName, bean.getClass() ).getReadMethod().invoke( bean ) );
    }
    return result;
}

次に、次のような呼び出しを行うことができます。

List<String > result = getMemberList( phonenumberList, "number", String.class );
于 2010-02-03T20:15:13.817 に答える
2

これは、ジェネリックとユーティリティ クラスを使用して行うことができます。コンパイル時に、取得するプロパティが存在すること (およびスペルミスなどがないこと) を確認できるため、リフレクションを使用するよりもこれが少し優れています。

まず、実際の変換を行うクラス。getListOfProperties() を呼び出すときに、匿名の内部クラスでオーバーライドする抽象 "get" メソッドに注意してください。

public abstract class ListPropertyGetter<R,T>
{
  /** Given a source object, returns some property of type R. */ 
  public abstract R get(T source);

  /** Given a list of objects, use the "get" method to retrieve a single property
      from every list item and return a List of those property values. */
  public final List<R> getListOfProperties(List<T> list)
  {
    List<R> ret = new ArrayList<R>(list.size());
    for(T source : list)
    {
      ret.add(get(source));
    }
    return ret;
  }
}

次に、このように使用します。きれいなワンライナーではありませんが、コンパイル時のチェックの良さ:

List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
// add some PhoneNumbers to the list
List<String> extensions =
  new ListPropertyGetter<String, PhoneNumber>()
  {
    @Override
    public String get(PhoneNumber source)
    {
      return source.getExtension();
    }
  }.getListOfProperties(phoneNumbers);
于 2010-02-03T21:09:18.310 に答える
1

リフレクション(java.lang.Classおよびjava.lang.reflect。*)を使用して、メソッド名を取得できます。「get」で始まるものはプロパティであり、その名前は「get」に続きます。

于 2010-02-03T20:15:27.547 に答える
1

これは、Javaでのクロージャの非常に良いケースです。来ていますが、まだここにはありません。

それまでの間、リフレクションを使用してこれを行うことができますが、リフレクションには常にパフォーマンスの低下があります。リフレクションでできることの1つは、メソッド/プロパティの名前を文字列として指定することにより、オブジェクトのメソッドを呼び出したり、プロパティを取得したりできるようにすることです。あなたの場合、あなたはやりたいと思うでしょう、getListOfProperties(AddressList, "city")そしてそのメソッドの中でリフレクションを使って指定されたプロパティを取得します。

このタイプのものは、ApacheCommonsBeanUtilsライブラリを使用することで劇的に簡素化されます。

import org.apache.commons.beanutils.BeanUtils;

static List<String> getListOfProperties(List beans, String propertyName) {
    List<String> propertyValues = new ArrayList<String>();
    for (Object bean:beans) {
         propertyValues.add(BeanUtils.getProperty(bean, propertyName));
    }
    return propertyValues;
}
于 2010-02-03T20:17:16.187 に答える