Are there any issues in this `Lazy` implementation? 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&lt;A&gt; {
  public abstract A apply();
}

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

  private Lazy(F0&lt;A&gt; init) {
    this.init = init;
  }

  public static &lt;A&gt; Lazy&lt;A&gt; initializedAs(F0&lt;A&gt; init) {
    return new Lazy&lt;A&gt;(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&lt;String&gt; minimumRequiredJavaVersion = Lazy.initializedAs(
    new F0&lt;String&gt;() {
      @Override
      public String apply() {
        return SystemProperties.isWindows() &amp;&amp; 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();
  }
};
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.