Java 8 方法引用及匿名内部类

Java 8 方法引用的介绍与示例参见:https://www.cnblogs.com/xingzc/p/6002873.html

在 Java 的 .class 字节码文件中,方法引用是通过 invoke-dynamic 指令来实现的,可以通过 javap -c xxx.class 对代码进行反汇编查看到。
但是在 Android 的 .dex/.smali 字节码文件中,由于 ART/Davilk 虚拟机并没有实现类似于 invoke-dynamic 的指令(参见:https://source.android.google.cn/devices/tech/dalvik/dalvik-bytecode ),所以 Android 编译器在把 .class 字节码转换成 .smali 字节码的过程中,会把方法引用的 invoke-dynamic 指令转换成等效匿名内部类代码指令来实现。

下面代码中的等效代码是通过反编译使用了方法引用的 Android APK 的代码来反推得到的。
(在 Android Studio 里写代码,编译出 apk,再通过 apktool 反编译 apk 得到 smali 代码,最后通过 smali 代码反推出 java 代码)

class Car {
    public static void say(Car car) {
        System.out.println("This is " + car);
    }

    public void run() {
        System.out.println(this + " running");
    }

    public void follow(Car another) {
        System.out.println(this + " following " + another);
    }
}

public class SupplierTest {
    
    
    public static Car create(Supplier<Car> supplier) {
        return supplier.get();
    }

    public static Car testCreate() {
        Car ret = create(Car::new); // 构造器引用,语法是Class::new,或者更一般的形式:Class<T>::new。注意:这个构造器没有参数。
        ret = create(Lambda$0.$instance); // 等效代码 Equivalent code

        return ret;
    }

    public static void main(String[] args) {
        final Car car = testCreate();
        final List<Car> cars = Arrays.asList(car);

        cars.forEach(Car::say); // 静态方法引用,语法是Class::static_method。注意:这个方法接受一个Car类型的参数。
        cars.forEach(Lambda$1.$instance); // 等效代码 Equivalent code

        cars.forEach(Car::run); // 成员方法的引用,语法是Class::method。注意,这个方法没有定义入参。
        cars.forEach(Lambda$2.$instance); // 等效代码 Equivalent code

        final Car police = testCreate();
        System.out.println(police + " is a police car");

        cars.forEach(police::follow); // 某个实例对象的成员方法的引用,语法是instance::method。注意:这个方法接受一个Car类型的参数。
        cars.forEach(Lambda$3.get$Lambda(police)); // 等效代码 Equivalent code
    }

    // for Car::new
    static final class Lambda$0 implements Supplier<Car> {
        static final Supplier<Car> $instance = new Lambda$0();

        @Override
        public Car get() {
            return new Car();
        }
    }

    // for Car::say (static method)
    static final class Lambda$1 implements Consumer<Car> {
        static final Consumer<Car> $instance = new Lambda$1();

        @Override
        public void accept(Car car) {
            Car.say(car);
        }
    }

    // for Car::run (non-static method)
    static final class Lambda$2 implements Consumer<Car> {
        static final Consumer<Car> $instance = new Lambda$2();

        @Override
        public void accept(Car car) {
            car.run();
        }
    }

    // for police::follow
    static final class Lambda$3 implements Consumer<Car> {
        private final Car arg$1;

        private Lambda$3(Car police) {
            arg$1 = police;
        }

        static Consumer<Car> get$Lambda(Car police) {
            return new Lambda$3(police);
        }

        @Override
        public void accept(Car car) {
            arg$1.follow(car);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/hegan2010/article/details/79243561
今日推荐