Predicate with Reflection in java [closed]

二次信任 提交于 2021-02-08 10:15:12

问题


class DataObject
{
String attr1;
String attr2;
String attr3;

// getters of three fields(getAttr1(),getAttr2() and getAttr3())
// setters of three fields(setAttr1(),setAttr2() and setAttr3())
}   

     List<DataObject> result = null;//Output List of objects of 'DataObject' class

    List<DataObject> dataObjectList; // Input List of objects of 'DataObject'class. 
Predicate<DataObject>  first= e -> e.getAttr1().equals("Value1_1");
result = dataObjectList.stream().filter(first).collect(Collectors.toList());

I want to filter my list of objects based on the conditions at runtime(Here condition is attr1 = "Value1_1"). My problem is that I will get the method name only in run time(It can be getAttr1() or getAttr2() or getAttr3() or any other function). I used reflection to solve this scenario.

Class<?> cls = Class.forName("com.example.java.DataObject");        
Class<?> noparams[] = {};
Method method = cls.getDeclaredMethod("getAttr1", noparams);
Predicate<DataObject>  first= e -> method.equals("Value1_1");

But the code will not give the required result. Please correct my code on reflection. Also please give me any alternative solutions.


回答1:


You've to actually invoke the method to get the result back using Method#invoke() method. Right now, you're just comparing the Method object. Change that to:

Predicate<DataObject>  first= e -> method.invoke(e).equals("Value1_1");

But that's really a weird way. I'm sure there can be some other way, if you can show what exactly you're trying to do.




回答2:


Are you dead-set on doing this with reflection? Reflection is often more trouble than it's worth. How about this:

class DataObject {
    static enum Attr {
        Attr1(DataObject::getAttr1),
        Attr2(DataObject::getAttr2),
        Attr3(DataObject::getAttr3),
        Attr4(DataObject::getAttr4);

        final Function<DataObject, Object> getter;

        Attr(Function<DataObject, Object> getter) {
            this.getter = requireNonNull(getter);
        }
    }

    // .... rest of the class ....

}


Attr attribute = Attr.valueOf("Attr1");

List<DataObject> filtered = dataObjectList.stream()
        .filter(e -> "Value_1".equals(attribute.getter.apply(e)))
        .collect(toList());

Obviously, the downside is that you would have to add an enum value for every attribute. But the upside is simplicity and the ability to refer to your attributes by type-safe enum rather than by strings. It will also be very easy to get a list of valid attributes (Attr.values()).

Once you set that up, you can do fun things like adding the following to your enum:

<T> Predicate<DataObject> matches(Predicate<T> p) {
    return e -> p.test((T)getter.apply(e));
}

And then you'll be able to write your code like this:

Attr attribute = Attr.valueOf("Attr1");

List<DataObject> filtered = dataObjectList.stream()
        .filter(attribute.matches("Value_1"::equals))
        .collect(toList());


来源:https://stackoverflow.com/questions/29506571/predicate-with-reflection-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!