java引用赋值和直接赋值_【Java】请问方法引用之后如何赋值

我现在想实现这种的效果

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

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

@FunctionalInterface

public interface FunctionOperation 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 Object setProperty1(Object object, FunctionOperation 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 Object setProperty1(Object object, FunctionOperation a,FunctionOperation 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中提供了有没有根据两个参数做操作,但是返回void的FunctionalInterface呢?当然有的,那就是BiComsumer

52599e8638b12f1421f51cad7067d5a8.png

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

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

BiConsumer 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方法直接做写入的,题主之前用的JavaBeans的PropertyDescriptor,如果要按照PropertyDescriptor的方式写一个lambda表达式,那就是另一种写法

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

BiConsumer consumerName = (u, value) ->

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

BiConsumer consumerAge = (u, value) ->

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

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

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

public interface CustomBiConsumer {

/**

* 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 consumerName = (u, value) ->

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

CustomBiConsumer consumerAge = (u, value) ->

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

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

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

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

一个输入,一个输出的FunctionalInterface,在jdk里有么?

有!那就是Function

5009d7365e0225f02e17ca46a1ec3762.png

所以我们就可以把consumerName和consumerName提取出一个公共的方法,这个公共方法的抽象就是一个Function>

它的实现写为

Function> consumerFunction =

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

.getWriteMethod()

.invoke(u, value);

所以我们之前的consumerName和consumerName就可以写做

Function> consumerFunction =

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

.getWriteMethod()

.invoke(u, value);

CustomBiConsumer consumerName = consumerFunction.apply("name");

CustomBiConsumer consumerAge = consumerFunction.apply("age");

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值