HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Are there any issues in this `Lazy` implementation?

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thisareissuesanylazyimplementationthere

Problem

I have written following small utility to abstract away the lazy initialization logic. (I tend to use lazy variables quite often.)

Are there any issues in this implementation?

// File: F0.java
public abstract class F0 {
  public abstract A apply();
}

// File: Lazy.java
public class Lazy {
  private boolean isInitialized = false;
  private A content;
  private final F0 init;

  private Lazy(F0 init) {
    this.init = init;
  }

  public static  Lazy initializedAs(F0 init) {
    return new Lazy(init);
  }

  @Override
  public String toString() {
    return this.get().toString();
  }

  public A get() {
    if (!isInitialized) {
      content = init.apply();
      isInitialized = true;
    }
    return content;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    Lazy lazy = (Lazy) o;
    Object c = this.get();
    if (c != null ? !c.equals(lazy.get()) : lazy.get() != null) {
      return false;
    }
    return true;
  }

  @Override
  public int hashCode() {
    return this.get().hashCode();
  }
}


Edit:

Here is an example usage from the current project I am working on.

final Prerequisite prerequisite = new Prerequisite() {

  private Lazy minimumRequiredJavaVersion = Lazy.initializedAs(
    new F0() {
      @Override
      public String apply() {
        return SystemProperties.isWindows() && SystemProperties.is64Bit() ? "1.7" : "1.6";
      }
    }
  );

  @Override
  public boolean isSatisfied() {
    return SystemProperties.javaVersionIsMinimum(minimumRequiredJavaVersion.get());
  }

  @Override
  public String failureMessage() {
    StringBuilder sb = new StringBuilder();
    sb.append("Minimum required Java version is: " + minimumRequiredJavaVersion.get() + "\n");
    sb.append("Your system has " + JAVA_SPECIFICATION_VERSION + ".");
    return sb.toString();
  }
};

Solution

Four notes:

-
It's not thread-safe. init.apply() could be called multiple times from different threads. (I don't know whether it is an issue or not.)

-
The constructor should check null inputs. (Effective Java 2nd Edition, Item 38: Check parameters for validity)

-
You should use append instead of String concatenation:

StringBuilder sb = new StringBuilder();
sb.append("Minimum required Java version is: ").append(minimumRequiredJavaVersion.get()).append("\n");
sb.append("Your system has ").append(JAVA_SPECIFICATION_VERSION).append(".");
return sb.toString();


-
Instead of the anonymous Prerequisite inner class I'd use a named top-level class (for example, MinimumRequiredJavaVersionPrerequisite). I think it's easier to read, naming it helps readers to understand the purpose of the class.

Code Snippets

StringBuilder sb = new StringBuilder();
sb.append("Minimum required Java version is: ").append(minimumRequiredJavaVersion.get()).append("\n");
sb.append("Your system has ").append(JAVA_SPECIFICATION_VERSION).append(".");
return sb.toString();

Context

StackExchange Code Review Q#12250, answer score: 2

Revisions (0)

No revisions yet.