Does Java have lazy evaluation?

后端 未结 9 1524
面向向阳花
面向向阳花 2020-12-03 16:44

I know that Java has smart/lazy evaluation in this case:

public boolean isTrue() {
    boolean a = false;
    boolean b = true;
    return b || (a &&         


        
相关标签:
9条回答
  • 2020-12-03 17:15

    Yes isATrue() will be called because you are calling it explicitly in line boolean a = isATrue();

    But it won't be called in following case if isBTrue() returns true:

    public boolean isTrue() {
        return isBTrue() || isATrue();
    }
    
    0 讨论(0)
  • 2020-12-03 17:22

    Is isATrue() called if isBTrue() returns true?

    Yes, both are called.

    0 讨论(0)
  • 2020-12-03 17:23

    No, it does not. isBTrue() will be invoked, regardless of the result of isATrue(). You can verify this yourself by writing such a program, with print statements in each of the methods.

    0 讨论(0)
  • 2020-12-03 17:24

    Well, as far as the language is concerned - yes, both functions are called.

    If you rewrote the function to this:

    public boolean isTrue() {
        return isBTrue() || isATrue();
    }
    

    then the second function will not be called, if the first is true.


    But this is short-circuit evaluation, not lazy evaluation. Lazy evaluation case would look something like this:

    public interface LazyBoolean {
        boolean eval();
    }
    
    class CostlyComparison implements LazyBoolean {
      private int a, b;
    
      public CostlyComparison(int a, int b) { 
        this.a=a; 
        this.b=b; 
      }
    
      @Override 
      public boolean eval() {
        //lots of probably not-always-necessary computation here
        return a > b;
      }
    } 
    
    public LazyBoolean isATrue() {
      return new CostlyComparison(10,30);  //just an example
    }
    
    public boolean isTrue() {        // so now we only pay for creation of 2 objects
        LazyBoolean a = isATrue();   // but the computation is not performed; 
        LazyBoolean b = isBTrue();   // instead, it's encapsulated in a LazyBoolean
        return b.eval() || a.eval(); // and will be evaluated on demand;
                                     // this is the definition of lazy eval.
    }
    
    0 讨论(0)
  • 2020-12-03 17:28

    Just wanted to add in addition to what have been mentioned in this question thread, below is from Oracle Documentation on JVM

    a Java Virtual Machine implementation may choose to resolve each symbolic reference in a class or interface individually when it is used ("lazy" or "late" resolution), or to resolve them all at once when the class is being verified ("eager" or "static" resolution). This means that the resolution process may continue, in some implementations, after a class or interface has been initialized.

    reference

    and as an example of the classes that has lazy implementation is Stream, this is from Oracle Documentation on Stream

    Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.

    reference

    That being said, if you do the following, nothing will be displayed. Unless you add initiator.

    Steam.of(1, 2, 3, 4, 5).filter(number -> {
       System.out.println("This is not going to be logged");
       return true;
    });
    
    0 讨论(0)
  • 2020-12-03 17:33

    SE8 (JDK1.8) has introduced Lambda expressions, which can make lazy evaluations more transparent. Consider the statement in the main method of the following code:

    @FunctionalInterface
    public interface Lazy<T> {
       T value();
    }
    
    class Test {
       private String veryLongMethod() {
          //Very long computation
          return "";
       }
    
       public static <T> T coalesce(T primary, Lazy<T> secondary) {
          return primary != null? primary : secondary.value();
       }
    
       public static void main(String[] argv) {
          String result = coalesce(argv[0], ()->veryLongMethod());
       }
    }
    

    The called function coalesce returns the first given non-null value (as in SQL). The second parameter in its call is a Lambda expression. The method veryLongMethod() will be called only when argv[0] == null. The only payload in this case is inserting ()-> before the value to be lazily evaluated on demand.

    0 讨论(0)
提交回复
热议问题