Java 8 method references and anonymous inner classes

Refer to the introduction and examples of Java 8 method references: https://www.cnblogs.com/xingzc/p/6002873.html

In Java's .class bytecode file, method references are implemented through the invoke-dynamic instruction, which can be viewed by disassembling the code through javap -c xxx.class.
But in Android's .dex/.smali bytecode files, because the ART/Davilk virtual machine does not implement instructions similar to invoke-dynamic (see: https://source.android.google.cn/devices/tech/ dalvik/dalvik-bytecode ), so the Android compiler will convert the invoke-dynamic instructions referenced by the method into equivalent anonymous internal class code instructions in the process of converting .class bytecode into .smali bytecode.

The equivalent code in the following code is obtained by decompiling the code of the Android APK referenced by the method.
(Write the code in Android Studio, compile the apk, then decompile the apk through apktool to get the smali code, and finally de-launch the java code through the smali code)

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);
        }
    }
}

Guess you like

Origin blog.csdn.net/hegan2010/article/details/79243561