我有几个看起来像这样的对象:
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编程语言可以完成许多神奇的事情。
答案 0 :(得分:2)
您可以使用Introspector
处理对象,例如this SO answer。
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 );
答案 1 :(得分:2)
对于这么简单的事情,你最好只提供吸气剂和制定者。拒绝复制一行代码,你不会节省太多。更好的是,只需让你的IDE为你编写它。
答案 2 :(得分:2)
您可以使用泛型和实用程序类来完成这项工作。我比使用反射更喜欢这个,因为你得到编译时检查你正在检索的属性是否存在(并且没有拼写错误等)。
首先是进行实际转换的类。注意抽象的“get”方法,当我们调用getListOfProperties()时,我们将在匿名内部类中覆盖它。
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);
答案 3 :(得分:1)
您可以使用反射(java.lang.Class和java.lang.reflect。*)来获取方法名称;那些以“get”开头的属性,其名称后跟“get”。
答案 4 :(得分:1)
这是Java中闭包的一个很好的例子;它即将到来,但它还没有到来。
与此同时,你可以通过反射来做到这一点,尽管反射总是会有性能损失。反射可以做的一件事是让你通过将方法/属性的名称指定为字符串来调用对象上的方法或检索属性;在您的情况下,您可能希望getListOfProperties(AddressList, "city")
并在该方法中使用反射来检索指定的属性。
使用Apache Commons BeanUtils库可以大大简化这类事情。
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;
}