V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
yuhuzi
V2EX  ›  问与答

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

  •  1
     
  •   yuhuzi · 2019-04-10 11:47:40 +08:00 · 1759 次点击
    这是一个创建于 2063 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我自定义一个函数接口:

    @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。 有大佬能够指点一二吗,这个问题卡在心里很不舒服。

    12 条回复    2019-04-10 15:49:36 +08:00
    gz911122
        1
    gz911122  
       2019-04-10 12:32:34 +08:00
    function.getClass().getAnnotations()
    gz911122
        2
    gz911122  
       2019-04-10 12:37:41 +08:00
    @gz911122
    少了一个 function.getMethods()
    gogotanc
        3
    gogotanc  
       2019-04-10 12:43:43 +08:00
    Method method = function.getClass().getMethod("functionA");

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

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

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

    实际上,你发的代码中,完全是把 HandlerFunction 当成普通接口而非函数式接口使用。你没有贴出来 lambda 处的代码,我很怀疑你的 lambda 表达式 生成的是另一个匿名类,跟你的 functionA 没有任何关系。
    feiyuanqiu
        10
    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
        11
    leafin  
       2019-04-10 14:44:06 +08:00
    最重要的地方,调用 functionB 的代码你没有贴出来啊老哥,虽然我猜可能是#4 说的那样。
    hpeng
        12
    hpeng  
       2019-04-10 15:49:36 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3876 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:16 · PVG 12:16 · LAX 20:16 · JFK 23:16
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.