字节码分析-方法引用

源码

package java.bytecode;

import java.util.ArrayList;
import java.util.List;

/**
 * 方法引用示例 - 演示Java 8方法引用
 */
public class MethodReferenceExample {

    // 静态方法引用示例
    public void staticMethodReferenceExample() {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.forEach(System.out::println);
    }

    // 实例方法引用示例
    public void instanceMethodReferenceExample() {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("world");
        list.forEach(String::toUpperCase);
    }

    // 构造方法引用示例
    public void constructorReferenceExample() {
        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.stream()
            .map(Integer::new)
            .forEach(System.out::println);
    }
}

结构化反解析

(完整javap输出请查看:java/bytecode/MethodReferenceExample_javap.txt)

关键部分:

  public void staticMethodReferenceExample();
    Code:
        26: aload_1
        27: getstatic     #20                 // Field java/lang/System.out:Ljava/io/PrintStream;
        30: dup
        31: invokestatic  #26                 // Method java/util/Objects.requireNonNull:(Ljava/lang/Object;)Ljava/lang/Object;
        34: pop
        35: invokedynamic #32,  0             // InvokeDynamic #0:accept:(Ljava/io/PrintStream;)Ljava/util/function/Consumer;
        40: invokeinterface #36,  2           // InterfaceMethod java/util/List.forEach:(Ljava/util/function/Consumer;)V

BootstrapMethods:
  0: #107 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(...)
    Method arguments:
      #77 (Ljava/lang/Object;)V
      #79 invokevirtual java/io/PrintStream.println:(Ljava/lang/String;)V
      #86 (Ljava/lang/String;)V
  1: #107 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(...)
    Method arguments:
      #77 (Ljava/lang/Object;)V
      #87 invokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;
      #86 (Ljava/lang/String;)V
  2: #107 invokestatic java/lang/invoke/LambdaMetafactory.metafactory:(...)
    Method arguments:
      #94 (Ljava/lang/Object;)Ljava/lang/Object;
      #95 newinvokespecial java/lang/Integer."<init>":(Ljava/lang/String;)V
      #100 (Ljava/lang/String;)Ljava/lang/Integer;

详细说明

方法引用类型

方法引用也使用invokedynamic指令实现,通过LambdaMetafactory在运行时生成实现类。

1. 静态方法引用

System.out::println - 引用静态方法或实例方法

#79 invokevirtual java/io/PrintStream.println:(Ljava/lang/String;)V

2. 实例方法引用

String::toUpperCase - 引用实例方法

#87 invokevirtual java/lang/String.toUpperCase:()Ljava/lang/String;

3. 构造方法引用

Integer::new - 引用构造方法

#95 newinvokespecial java/lang/Integer."<init>":(Ljava/lang/String;)V

MethodHandle

方法引用通过MethodHandle表示要引用的方法:

实现机制

方法引用的实现机制与Lambda表达式相同:
1. 使用invokedynamic指令
2. 引导方法为LambdaMetafactory.metafactory
3. 通过MethodHandle引用目标方法
4. 运行时动态生成实现类

与Lambda的区别

性能优势

方法引用通常比Lambda表达式更高效,因为:
- 不需要生成Lambda方法
- 直接引用目标方法
- JVM可以更好地优化