Java 关于函数式接口 和注解的一个问题(不好意思,刚才没有用 md 的语法,排版不好)

2019-04-10 11:47:40 +08:00
 yuhuzi

我自定义一个函数接口:

@FunctionalInterface
public interface HandlerFunction {
	void callback(); 
}

然后自定义了一个方法级的注解 @Great:

@Target({ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME)
@Documented public
@interface Great { 
	boolean value() default true;
}

现在我给方法 A ( functionA )加上 @Great 注解,functionA 满足函数接口 HandlerFunction,再将 functionA 传到方法 B ( functionB )中去,方法 B 的参数中接收 HandlerFunction 类的方法,要如何在 functionB 中拿到 functionA 的注解 @Great 呢?代码如下:

@Greet
public void functionA() {
	System.out.println("hello world");
}
public void functionB(HandlerFunction function) { 
	//要如何在这里拿到传入的 function 的注解呢?
	function.callback();
	// 回调传入的 function
}

我现在 getMethod 只能拿到一个 lambda 表达式,如 function: AppTest$lambda@970,而不是具体的 functionA。 有大佬能够指点一二吗,这个问题卡在心里很不舒服。

1740 次点击
所在节点    问与答
12 条回复
gz911122
2019-04-10 12:32:34 +08:00
function.getClass().getAnnotations()
gz911122
2019-04-10 12:37:41 +08:00
@gz911122
少了一个 function.getMethods()
gogotanc
2019-04-10 12:43:43 +08:00
Method method = function.getClass().getMethod("functionA");

Great great = method.getAnnotation(Great.class);
kiddult
2019-04-10 12:50:02 +08:00
现在明白是什么情况了,你调用 functionB 的时候,参数是 functionA 的 method reference,也就是 functionB(this::functionA)?

Java 目前没有提供 method reference 的 method literals 功能,后面可能会补上?

如果是在调用函数之后确定类,可以在通过代理来记录,虽然就是很讨巧了
MoHen9
2019-04-10 12:53:07 +08:00
挺难拿到的,function 对象无法获取 functionA 方法所在 class 的信息,所以没法获取 A 方法的 method,除非你在 HandlerFunction 的方法中传一个 A 方法的 class 过去
MoHen9
2019-04-10 12:57:23 +08:00
不太理解什么意思,是在 HandlerFunction 的 callback 方法中执行 A 方法,然后在 B 方法中获取 A 方法的注解信息?
yuhuzi
2019-04-10 13:19:53 +08:00
@kiddult 是你说的这个意思,我发现应该是 java8 不支持,不然不会这么费劲。
SoloCompany
2019-04-10 13:43:09 +08:00
method reference 是拿不到包装的 method instance 的,而且很可能编译阶段都不会存下来,你运行时 inspect 一下 lambda object 的数据结构就清楚了
passerbytiny
2019-04-10 13:53:28 +08:00
你已经把我搞糊涂了,函数式接口以及 lambda 都是用来快速定义匿名内部类的,而注解是用来标记东西的,二者用在一起很怪异,因为通常只会标记非匿名的东西,匿名的东西都是随创建随用,用完就销毁的。

实际上,你发的代码中,完全是把 HandlerFunction 当成普通接口而非函数式接口使用。你没有贴出来 lambda 处的代码,我很怀疑你的 lambda 表达式 生成的是另一个匿名类,跟你的 functionA 没有任何关系。
feiyuanqiu
2019-04-10 13:54:18 +08:00
怎么又来一个帖子...在另外一个帖子回复了,这里粘贴一下:

拿不到,原因是 lambda 的实现方式其实是在运行时动态生成一个匿名内部类,在生成类的 callback 方法里,再去调用 functionA。

反编译 .class 可以得到这个动态生成的类:

final class Test$$Lambda$1 implements Test$HandlerFunction {
public void callback();
Code:
0: aload_0
1: getfield #15 // Field arg$1:LTest;
4: invokevirtual #26 // Method Test.functionA:()V
7: return
}
leafin
2019-04-10 14:44:06 +08:00
最重要的地方,调用 functionB 的代码你没有贴出来啊老哥,虽然我猜可能是#4 说的那样。
hpeng
2019-04-10 15:49:36 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/553668

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX