如何获取我的对象的特定属性?

时间:2013-12-08 16:22:12

标签: java reflection

假设我有这门课。

class People {
    private String name;
    private int age;
    /** other stuff constructor / getters / setters / etc. **/
}

让我说我有这个清单:

List<People> people = Arrays.asList(new People("Mark", 21), new People("Bob",17), new People("Alex", 22));

现在我希望能够为特定属性的所有用户获得List

使用Java 8,我可以创建一个接受我想要的函数的方法:

public static <X, Y> List<Y> processElements(Iterable<X> source, Function <X, Y> mapper) {
    List<Y> l = new ArrayList<>();
    for (X p : source) 
        l.add(mapper.apply(p));
    return l;
}

然后我将能够执行一些调用:

List<String> listNames = processElements(people, p -> p.getName()); 
List<Integer> listAges = processElements(people, p -> p.getAge()); 

然而,在Java 7中这是不可能的(我知道它存在于Guava中,但我只想使用JDK来提出解决方案)。

这与我使用反射的方式有关:

public static List<Object> processElements(List<People> l, String fieldName) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
        Field field = People.class.getDeclaredField(fieldName);
        field.setAccessible(true);
        List<Object> list = new ArrayList<>();
        for(People p : l){
            list.add(field.get(p));
        }
        field.setAccessible(false);
        return list;
}

现在我可以做List<Object> listNames = processElements(people, "name");之类的工作。

但我觉得不舒服:

  1. 我收到List<Object>
  2. 每当我使用反射时,我总觉得它存在一个更好的实现,而不是使用它
  3. 使用field.setAccessible(true);不是很安全
  4. 所以我的问题是:

    1. 如果不使用JDK的反射(不使用Guava或Functional Java),是否可以做同样的事情?
    2. 如何根据我作为参数传递给我的方法的字段类型获取String或Integer列表?
    3. 由于

2 个答案:

答案 0 :(得分:6)

您可以使用Java 7的匿名类完成与Java 8完全相同的操作

public static <X, Y> List<Y> processElements(Iterable<X> source, Function <X, Y> mapper) {
    List<Y> l = new ArrayList<>();
    for (X p : source) 
        l.add(mapper.apply(p));
    return l;
}

List<String> listNames = processElements(people, new Function<People, String>() {
    public String apply(People person) {
        return person.getName();
    }
}); 

答案 1 :(得分:2)

在Java 8中,您可以按如下方式执行此操作:

List<String> names = people.stream()
    .map(Person::getName).collect(Collectors.asList());

您的Java 8解决方案也适用于Java 7,因为它不使用任何特殊语言构造,而只使用Java 8中引入的接口Function。如果您需要这样的接口,您可以简单地声明它你自己!

public interface Function<T, R> {
    R apply(T t);
}