Lambda expression vs method reference implementation details

后端 未结 3 1533
梦如初夏
梦如初夏 2021-01-05 15:43

Given this:

class MyClass {
    static class A {
        public boolean property() {
            return Math.random() < 0.5;
        }
    }

    static L         


        
3条回答
  •  时光取名叫无心
    2021-01-05 16:13

    This is an extract from the Brian Goetz's doc linked by Brett Oken:

    When the compiler encounters a lambda expression, it first lowers (desugars) the lambda body into a method whose argument list and return type match that of the lambda expression, possibly with some additional arguments (for values captured from the lexical scope, if any.) At the point at which the lambda expression would be captured, it generates an invokedynamic call site, which, when invoked, returns an instance of the functional interface to which the lambda is being converted. This call site is called the lambda factory for a given lambda. The dynamic arguments to the lambda factory are the values captured from the lexical scope. The bootstrap method of the lambda factory is a standardized method in the Java language runtime library, called the lambda metafactory. The static bootstrap arguments capture information known about the lambda at compile time (the functional interface to which it will be converted, a method handle for the desugared lambda body, information about whether the SAM type is serializable, etc.)

    Method references are treated the same way as lambda expressions, except that most method references do not need to be desugared into a new method; we can simply load a constant method handle for the referenced method and pass that to the metafactory.

    Examples extracted from same doc:

    As an example, consider a lambda that captures a field minSize:

    list.filter(e -> e.getSize() < minSize )
    

    We desugar this as an instance method, and pass the receiver as the first captured argument:

    list.forEach(INDY((MH(metaFactory), MH(invokeVirtual Predicate.apply),
                        MH(invokeVirtual B.lambda$1))( this ))));
    
    private boolean lambda$1(Element e) {
        return e.getSize() < minSize; }
    

    While

    list.filter(String::isEmpty)
    

    is translated as:

    list.filter(indy(MH(metaFactory), MH(invokeVirtual Predicate.apply),
                 MH(invokeVirtual String.isEmpty))()))
    

提交回复
热议问题