i trying list of property ,means have class user , has property name , have public method getname() name of user, problem want create method takes generic list , , method name , , helping of stream api list of property of class.
means if pass list of user , method name 'getname' in test method returns list of username.
public static boolean test(list<?> propertylist) throws exception{ class<?> c = class.forname(propertylist.get(0).getclass().getcanonicalname()); method method = c.getdeclaredmethod(methodname); !propertylist.stream().map(c::method).allmatch(new hashset<>()::add); }
you can’t put class
object , method
object using ::
c::method
. can express dynamic invocation using method::invoke
, unfortunately, that’ll incompatible expected type function
, because method.invoke
can throw checked exceptions.
so can use lambda expression encapsulating dynamic invocation , catching reflective exceptions:
public static boolean test(list<?> propertylist, string methodname) throws exception{ method method = propertylist.get(0).getclass().getdeclaredmethod(methodname); return !propertylist.stream().map(x -> { try { return method.invoke(x); } catch (reflectiveoperationexception ex) { throw new runtimeexception("invoking "+method, ex); } }).allmatch(new hashset<>()::add); }
if using method
function
recurring problem in code, can create factory method utilizing java’s built-in features dynamic class creation:
public static boolean test(list<?> propertylist, string methodname) throws exception { method method = propertylist.get(0).getclass().getdeclaredmethod(methodname); return !propertylist.stream().map(tofunction(method)).allmatch(new hashset<>()::add); } public static function tofunction(method m) throws illegalaccessexception { return methodhandleproxies.asinterfaceinstance(function.class, methodhandles.lookup().unreflect(m)); }
but note there conceptional flaws in method. relies on list
not being empty , imposes unintended constraints on type of first list element. list may contain elements of different actual types having common base type declared element type. if elements have same type, getdeclaredmethod
search specific class , ignore inherited methods.
in other words, using "tostring"
method name can fail procedure not object.tostring
, may fail find method or may find method in first element’s type specific other elements of list.
a better design let caller provide type:
public static <t> boolean test( list<? extends t> propertylist, class<t> type, string methodname) throws exception { method method = type.getmethod(methodname); return !propertylist.stream().map(tofunction(method)).allmatch(new hashset<>()::add); }
this allows pass in list having declared element type being more specific type of class search method , having particular elements of more specific type declare element type , supports empty lists.
note getmethod
’s search consider inherited methods public
methods.
Comments
Post a Comment