Java方法引用是否创建对象?底层字节码实现解析
Java Lambda与方法引用的对象创建疑问
你说得对,Lambda表达式确实会被实例化为函数式接口的对象,比如这段代码:
myList.stream().map(x->x.getName().replaceAll('a','b')).toList();
或者等价写法:
Function<MyObject,String> myFunc = x -> {return x.getName().replaceAll('a','b');} myList.stream().map(myFunc).toList();
这里的x->x.getName().replaceAll('a','b')确实会触发函数式接口对象的创建,涉及内存分配,底层会有new操作(不过JVM可能会做实例复用的优化,但语义上是创建了对象)。
针对你提出的方法引用相关问题,解答如下:
1. 实例方法与静态方法引用是否会被包装进函数式接口?
是的,不管是this::myFilter这种实例方法引用,还是A::staticFilter这种静态方法引用,都会被包装成对应的函数式接口对象(这里是Predicate<String>)。
- 对于
this::myFilter,会创建一个持有当前A类实例引用的函数式接口对象,当调用该接口的方法时,会触发对该实例的myFilter方法调用。 - 对于
A::staticFilter,创建的函数式接口对象不需要持有实例,调用时直接触发静态方法执行。
2. 字节码层面是否有特殊处理?
在字节码层面,方法引用和Lambda的处理逻辑类似,但有一些语法层面不直观的细节:
- 两者都会通过
invokedynamic指令动态生成函数式接口的实现类实例,而不是直接在代码里显式写new关键字。 - 方法引用对应的
invokedynamic指令会指向一个引导方法,该方法会根据引用的是实例方法还是静态方法,生成对应的函数式接口实现:- 静态方法引用生成的实现类,其接口方法会直接调用目标静态方法;
- 实例方法引用生成的实现类会持有目标实例,接口方法调用时会用这个实例调用目标方法。
- Java本身没有方法指针的概念,但
invokedynamic的处理逻辑让方法引用的调用效率接近直接方法调用,同时JVM会做实例复用等优化,减少内存分配的开销。
内容的提问来源于stack exchange,提问作者arso
相关产品推荐
相关产品推荐

