【Java】请问方法引用之后如何赋值

我现在想实现这种的效果

Beanutils.setProperty1(user, User::getName);

我参照网上的例子定义了一个接口类

@FunctionalInterface

public interface FunctionOperation<T> extends Serializable {

//这里只接收无参方法

Object get(T source);

//这个方法返回的SerializedLambda是重点

default SerializedLambda getSerializedLambda() throws Exception {

//writeReplace改了好像会报异常

Method write = this.getClass().getDeclaredMethod("writeReplace");

write.setAccessible(true);

return (SerializedLambda) write.invoke(this);

}

default String getImplClass() {

try {

return getSerializedLambda().getImplClass();

} catch (Exception e) {

return null;

}

}

default String getImplMethodName() {

try {

return getSerializedLambda().getImplMethodName();

} catch (Exception e) {

return null;

}

}

定义了实现方法

    public static <T>  Object setProperty1(Object object, FunctionOperation<T> a)  {

try{

}catch (Exception e){

e.printStackTrace();

}

return object;

}

我在这里边如何操作,其他服务调用这个方法的时候

Beanutils.setProperty1(user, User::getName);

当我这么调用的时候,我希望在上边那个实现方法里给这个name赋值比如说 “aaa”,但是我使用反射的方法好像没有成功,想问一下一般都是如何处理
<!-------------------------------------------------------->
修改:
我没有表述清楚我的想法,我现在有两个方法,这两个方法我希望实现的功能是一样的

 public static Object setProperty(Object object,String a,String b)  {

Class target = object.getClass();

try{

PropertyDescriptor descriptor = new PropertyDescriptor(a,target);

Method method= descriptor.getWriteMethod(); //

method.invoke(object,"1");

PropertyDescriptor descriptor2 = new PropertyDescriptor(b,target);

Method method2= descriptor.getWriteMethod(); //

method2.invoke(object,"1");

}catch (Exception e){

e.printStackTrace();

}

return object;

}

public static <T> Object setProperty1(Object object, FunctionOperation<T> a,FunctionOperation<T> b) {

try{

}catch (Exception e){

e.printStackTrace();

}

return object;

}

我在controller调用了这两个方法

public static void main(String[] args) {

User user = new User();

user.setAge("1111");

System.out.println(user.toString());

try {

Beanutils.setProperty(user,"name","age");

//想采用这种方式

Beanutils.setProperty1(user, User::getName,User::getAge);

} catch (Exception e) {

e.printStackTrace();

}

System.out.println(user);

}

一种格式是
Beanutils.setProperty(user,"name","age")
传递字符串这种,我希望可以传递User::getName这种,也就是下边这样
Beanutils.setProperty1(user, User::getName,User::getAge);
我尝试在setProperty1方法里也是用setProperty方法里的那种invoke但是好像没有效果。就卡住了我也不知道该怎么处理了

回答

看来后续的补充才算明白setProperty1只是为了设置默认的属性值,其实题主你之前写这个User::getName,User::getAge对我影响太大了,我老想到get操作去,你这个不是赋值,所以应该是set操作嘛

这个方法引用,其实就是lambda表达式嘛,方法引用只是快捷写法,那lambda表达式其实就是把方法做了抽象

而一个方法是需要关心输入和输出的,那lambda表达式也需要关注输入和输出。

题主想要setProperty1方法和setProperty效果一样,所以setProperty1方法中的参数传入的lambda表达式应该也要做到给属性赋值的操作。

那这个lambda表达式的输入是什么?

setProperty1方法中能给到的是参数有object对象以及默认的输入值"1",所以传入的lambda表达式的输入就应该是object"1",返回可以为空,因为这个lambda表达式里我只对某个属性做设置操作就可以了

那我们jdk中提供了有没有根据两个参数做操作,但是返回voidFunctionalInterface呢?当然有的,那就是BiComsumer

【Java】请问方法引用之后如何赋值

之前提到lambda表达式就是一个方法的抽象,所以我们可以看到BiComsumer这个方法的抽象要求有两个参数,然后返回void,因此我们就可以这样来设计setProperty1方法中后两个参数的传入

BiConsumer<User, String> consumerName = (u, str) -> u.setName(str);

BiConsumer<User, String> consumerAge = (u, str) -> u.setAge(str);

当然setProperty1方法就应该改为

public static Object setProperty1(Object object, 

BiConsumer consumer1,

BiConsumer consumer2) {

try{

consumer1.accept(object, "1");

consumer2.accept(object, "1");

}catch (Exception e){

e.printStackTrace();

}

return object;

}

最终直接调用为

Beanutils.setProperty1(user, consumerName, consumerAge);

当然现在这种写法是按照set方法直接做写入的,题主之前用的JavaBeansPropertyDescriptor,如果要按照PropertyDescriptor的方式写一个lambda表达式,那就是另一种写法

但是大体思路结构是类似的

BiConsumer<User, String> consumerName = (u, value) -> 

new PropertyDescriptor("name", u.getClass()).getWriteMethod().invoke(u, value);

BiConsumer<User, String> consumerAge = (u, value) ->

new PropertyDescriptor("age", u.getClass()).getWriteMethod().invoke(u, value);

看起来一样,不过你可以去试试,编译会报错的,在new PropertyDescriptor上,因为new PropertyDescriptor显示的抛出了异常,而我们的BiConsumeraccept方法没有throws 异常,因此要改的话,就不能在用BiComusmer了,需要自己写一个

比如我们写一个CustomBiComusmer,和BiComusmer类似,只是accept方法抛出异常即可

public interface CustomBiConsumer<T, U> {

/**

* Performs this operation on the given arguments.

*

* @param t the first input argument

* @param u the second input argument

*/

void accept(T t, U u) throws Exception;

}

然后把BiComsumer换成我们的CustomBiConsumer就可以啦,setProperty1方法中的参数也记得改哦

CustomBiConsumer<User, String> consumerName = (u, value) ->

new PropertyDescriptor("name", u.getClass()).getWriteMethod().invoke(u, value);

CustomBiConsumer<User, String> consumerAge = (u, value) ->

new PropertyDescriptor("age", u.getClass()).getWriteMethod().invoke(u, value);

这样就可以了么?其实还可以再精炼一点,我们平常写方法都会公共方法提到一起,那lambda表达式作为方法的抽象,当然也可以做一次整合

因为我们发现consumerNameconsumerAge非常接近,他们的差别只是参数传入的"name""age"的差距,其他都一样

因此此时如果再把这种我们要处理的情况看成是一个方法,那根据我们之前说的,此时方法的输入应该是一个属性名,只有一个输入,输出是什么?那当然是我们要的CustomBiConsumer

一个输入,一个输出的FunctionalInterface,在jdk里有么?
有!那就是Function
【Java】请问方法引用之后如何赋值

所以我们就可以把consumerNameconsumerName提取出一个公共的方法,这个公共方法的抽象就是一个Function<String, CustomBiConsumer<User, String>>

它的实现写为

Function<String, CustomBiConsumer<User, String>> consumerFunction = 

propName -> (u, value) -> new PropertyDescriptor(propName, u.getClass())

.getWriteMethod()

.invoke(u, value);

所以我们之前的consumerNameconsumerName就可以写做

Function<String, CustomBiConsumer<User, String>> consumerFunction = 

propName -> (u, value) -> new PropertyDescriptor(propName, u.getClass())

.getWriteMethod()

.invoke(u, value);

CustomBiConsumer<User, String> consumerName = consumerFunction.apply("name");

CustomBiConsumer<User, String> consumerAge = consumerFunction.apply("age");

以上就是简单的想法把,感觉题主可能对于lambda表达式还不是很透彻,如果你能把后几个用例看明白,尤其是consumerFunction看懂,估计也就没什么问题啦,仅供参考哈,债见ヾ( ̄▽ ̄)Bye~Bye~

以上是 【Java】请问方法引用之后如何赋值 的全部内容, 来源链接: utcz.com/a/88407.html

回到顶部