diff options
-rw-r--r-- | buildScripts/website.ant.xml | 6 | ||||
-rw-r--r-- | usage_examples/EqualsAndHashCodeExample_post.jpage | 16 | ||||
-rw-r--r-- | usage_examples/GetterLazyExample_post.jpage | 25 | ||||
-rw-r--r-- | usage_examples/GetterLazyExample_pre.jpage | 13 | ||||
-rw-r--r-- | usage_examples/valExample_post.jpage | 21 | ||||
-rw-r--r-- | usage_examples/valExample_pre.jpage | 20 | ||||
-rw-r--r-- | website/features/EqualsAndHashCode.html | 8 | ||||
-rw-r--r-- | website/features/GetterLazy.html | 65 | ||||
-rw-r--r-- | website/features/GetterSetter.html | 9 | ||||
-rw-r--r-- | website/features/Log.html | 9 | ||||
-rw-r--r-- | website/features/ToString.html | 2 | ||||
-rw-r--r-- | website/features/index.html | 4 | ||||
-rw-r--r-- | website/features/val.html | 65 |
13 files changed, 253 insertions, 10 deletions
diff --git a/buildScripts/website.ant.xml b/buildScripts/website.ant.xml index 1d14097c..ef12026e 100644 --- a/buildScripts/website.ant.xml +++ b/buildScripts/website.ant.xml @@ -112,6 +112,9 @@ such as converting the changelog into HTML, and creating javadoc. <param name="transformationName" value="GetterSetter" /> </antcall> <antcall target="-integrateSnippet"> + <param name="transformationName" value="GetterLazy" /> + </antcall> + <antcall target="-integrateSnippet"> <param name="transformationName" value="ToString" /> </antcall> <antcall target="-integrateSnippet"> @@ -135,6 +138,9 @@ such as converting the changelog into HTML, and creating javadoc. <antcall target="-integrateSnippet"> <param name="transformationName" value="Log" /> </antcall> + <antcall target="-integrateSnippet"> + <param name="transformationName" value="val" /> + </antcall> </target> <target name="-website-dist"> diff --git a/usage_examples/EqualsAndHashCodeExample_post.jpage b/usage_examples/EqualsAndHashCodeExample_post.jpage index 312bb92f..189a520e 100644 --- a/usage_examples/EqualsAndHashCodeExample_post.jpage +++ b/usage_examples/EqualsAndHashCodeExample_post.jpage @@ -15,8 +15,9 @@ public class EqualsAndHashCodeExample { @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; - if (o.getClass() != this.getClass()) return false; + if (!(o instanceof EqualsAndHashCodeExample)) return false; EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o; + if (!other.canEqual(this)) return false; if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false; if (Double.compare(this.score, other.score) != 0) return false; if (!Arrays.deepEquals(this.tags, other.tags)) return false; @@ -33,6 +34,10 @@ public class EqualsAndHashCodeExample { return result; } + public boolean canEqual(Object other) { + return other instanceof EqualsAndHashCodeExample; + } + public static class Square extends Shape { private final int width, height; @@ -44,9 +49,10 @@ public class EqualsAndHashCodeExample { @Override public boolean equals(Object o) { if (o == this) return true; if (o == null) return false; - if (o.getClass() != this.getClass()) return false; - if (!super.equals(o)) return false; + if (!(o instanceof Square)) return false; Square other = (Square) o; + if (!other.canEqual(this)) return false; + if (!super.equals(o)) return false; if (this.width != other.width) return false; if (this.height != other.height) return false; return true; @@ -60,5 +66,9 @@ public class EqualsAndHashCodeExample { result = (result*PRIME) + this.height; return result; } + + public boolean canEqual(Object other) { + return other instanceof Square; + } } } diff --git a/usage_examples/GetterLazyExample_post.jpage b/usage_examples/GetterLazyExample_post.jpage new file mode 100644 index 00000000..76101db1 --- /dev/null +++ b/usage_examples/GetterLazyExample_post.jpage @@ -0,0 +1,25 @@ +public class GetterLazyExample { + private int[] $lombok$lazy1v; + private volatile boolean $lombok$lazy1i; + private final Object $lombok$lazyLock = new Object[0]; + + public int[] getCached() { + if (!this.$lombok$lazy1i) { + synchronized (this.$lombok$lazyLock) { + if (!this.$lombok$lazy1i) { + this.$lombok$lazy1v = expensive(); + this.$lombok$lazy1i = true; + } + } + } + return this.$lombok$lazy1v; + } + + private int[] expensive() { + double[] result = new double[1000000]; + for (int i = 0; i < result.length; i++) { + result[i] = Math.asin(i); + } + return result; + } +} diff --git a/usage_examples/GetterLazyExample_pre.jpage b/usage_examples/GetterLazyExample_pre.jpage new file mode 100644 index 00000000..a6ca0966 --- /dev/null +++ b/usage_examples/GetterLazyExample_pre.jpage @@ -0,0 +1,13 @@ +import lombok.Getter; + +public class GetterLazyExample { + @Getter(lazy=true) private final int[] cached = expensive(); + + private int[] expensive() { + double[] result = new double[1000000]; + for (int i = 0; i < result.length; i++) { + result[i] = Math.asin(i); + } + return result; + } +} diff --git a/usage_examples/valExample_post.jpage b/usage_examples/valExample_post.jpage new file mode 100644 index 00000000..e0f983d9 --- /dev/null +++ b/usage_examples/valExample_post.jpage @@ -0,0 +1,21 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class ValExample { + public String example() { + final ArrayList<String> example = new ArrayList<String>(); + example.add("Hello, World!"); + String foo = example.get(0); + return foo.toLowerCase(); + } + + public void example2() { + final HashMap<Integer, String> map = new HashMap<Integer, String>(); + map.put(0, "zero"); + map.put(5, "five"); + for (final Map.Entry<Integer, String> entry : map.entrySet()) { + System.out.printf("%d: %s\n", entry.getKey(), entry.getValue()); + } + } +} diff --git a/usage_examples/valExample_pre.jpage b/usage_examples/valExample_pre.jpage new file mode 100644 index 00000000..8b9dadc3 --- /dev/null +++ b/usage_examples/valExample_pre.jpage @@ -0,0 +1,20 @@ +import java.util.ArrayList; +import java.util.HashMap; + +public class ValExample { + public String example() { + val example = new ArrayList<String>(); + example.add("Hello, World!"); + val foo = example.get(0); + return foo.toLowerCase(); + } + + public void example2() { + val map = new HashMap<Integer, String>(); + map.put(0, "zero"); + map.put(5, "five"); + for (val entry : map.entrySet()) { + System.out.printf("%d: %s\n", entry.getKey(), entry.getValue()); + } + } +} diff --git a/website/features/EqualsAndHashCode.html b/website/features/EqualsAndHashCode.html index c5128d10..dbe45218 100644 --- a/website/features/EqualsAndHashCode.html +++ b/website/features/EqualsAndHashCode.html @@ -28,10 +28,16 @@ </p><p> Setting <code>callSuper</code> to <em>true</em> when you don't extend anything (you extend <code>java.lang.Object</code>) is a compile-time error, because it would turn the generated <code>equals()</code> and <code>hashCode()</code> implementations into having the same behaviour as simply inheriting these methods from <code>java.lang.Object</code>: - only the same object will be equal to each other and will have the same hashCode. Obviously, inheriting <code>java.lang.Object</code> is the right strategy if you want this behaviour. + only the same object will be equal to each other and will have the same hashCode. Not setting <code>callSuper</code> to <em>true</em> when you extend another class generates a warning, because unless the superclass has no (equality-important) fields, lombok cannot generate an implementation for you that takes into account the fields declared by your superclasses. You'll need to write your own implementations, or rely on the <code>callSuper</code> chaining facility. + </p><p> + <em>NEW in Lombok 0.10: </em>Unless your class is <code>final</code> and extends <code>java.lang.Object</code>, lombok generates a <code>canEqual</code> method + which means JPA proxies can still be equal to their base class, but subclasses that add new state don't break the equals contract. The complicated reasons for + why such a method is necessary are explained in this paper: (TODO: Find link to Venners/Spoon/Odersky). If all classes in a hierarchy are a mix of scala case classes + and classes with lombok-generated equals methods, all equality will 'just work'. If you need to write your own equals methods, you should always override <code>canEqual</code> + if you change <code>equals</code> and <code>hashCode</code>. </p> </div> <div class="snippets"> diff --git a/website/features/GetterLazy.html b/website/features/GetterLazy.html new file mode 100644 index 00000000..a91e782c --- /dev/null +++ b/website/features/GetterLazy.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html><head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <link rel="stylesheet" type="text/css" href="../logi/reset.css" /> + <link rel="stylesheet" type="text/css" href="features.css" /> + <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" /> + <meta name="description" content="Spice up your java" /> + <title>@Getter(lazy=true)</title> +</head><body><div id="pepper"> + <div class="minimumHeight"></div> + <div class="meat"> + <div class="header"><a href="../index.html">Project Lombok</a></div> + <h1>@Getter and @Setter</h1> + <div class="byline">Laziness is a virtue!</div> + <div class="overview"> + <h3>Overview</h3> + <p> + <em>NEW IN Lombok 0.10: </em>You can let lombok generate a getter which will calculate a value once, the first time this getter is called, and cache it from then on. This can be useful + if calculating the value takes a lot of CPU, or the value takes a lot of memory. To use this feature, create a <code>private final</code> variable, + initialize it with the expression that's expensive to run, and annotate your field with <code>@Getter(lazy=true)</code>. The field will be hidden from the + rest of your code, and the expression will be evaluated no more than once, when the getter is first called. There are no magic marker values (i.e. even + if the result of your expensive calculation is <code>null</code>, the result is cached) and your expensive calculation need not be thread-safe, as lombok + takes care of locking. + </p> + </div> + <div class="snippets"> + <div class="pre"> + <h3>With Lombok</h3> + <div class="snippet">@HTML_PRE@</div> + </div> + <div class="sep"></div> + <div class="post"> + <h3>Vanilla Java</h3> + <div class="snippet">@HTML_POST@</div> + </div> + </div> + <div style="clear: left;"></div> + <div class="overview"> + <h3>Small print</h3><div class="smallprint"> + <p> + Lombok actually creates a few fields all prefixed with <code>$lombok$</code> to cache the value. You should not rely on the exact type, name, and structure + of these fields as future implementations may change them. To access the lazily initialized value, <em>always</em> use the generated getter. + </p><p> + Other Lombok annotations such as <code>@ToString</code> always call the getter even if you use <code>doNotUseGetters=true</code>. + </p> + </div> + </div> + <div class="footer"> + <a href="index.html">Back to features</a> | <a href="GetterSetter.html">Previous feature (@Getter / @Setter)</a> | <a href="ToString.html">Next feature (@ToString)</a><br /> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + </div> + <div style="clear: both;"></div> + </div> +</div> +<script type="text/javascript"> + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-9884254-1"); + pageTracker._trackPageview(); + } catch(err) {} +</script> +</body></html> diff --git a/website/features/GetterSetter.html b/website/features/GetterSetter.html index ea1af150..fd4ed17d 100644 --- a/website/features/GetterSetter.html +++ b/website/features/GetterSetter.html @@ -60,15 +60,18 @@ </p><p> Any annotations named <code>@NonNull</code> (case insensitive) on the field are interpreted as: This field must not ever hold <em>null</em>. Therefore, these annotations result in an explicit null check in the generated setter. Also, these - annotations (as well as any annotation named <code>@Nullable</code> or <code>@CheckForNull</code>) are copied to setter parameter and getter method + annotations (as well as any annotation named <code>@Nullable</code> or <code>@CheckForNull</code>) are copied to setter parameter and getter method. + </p><p> + You can annotate a class with a <code>@Getter</code> or <code>@Setter</code> annotation. Doing so is equivalent to annotating all non-static fields + in that class with that annotation. <code>@Getter</code>/<code>@Setter</code> annotations on fields take precedence over the ones on classes. </p><p> Using the <code>AccessLevel.NONE</code> access level simply generates nothing. It's useful only in combination with - <a href="Data.html"><code>@Data</code></a>. + <a href="Data.html"><code>@Data</code></a> or a class-wide <code>@Getter</code> or <code>@Setter</code>. </p> </div> </div> <div class="footer"> - <a href="index.html">Back to features</a> | <span class="disabled">Previous feature</span> | <a href="ToString.html">Next feature (@ToString)</a><br /> + <a href="index.html">Back to features</a> | <span class="disabled">Previous feature</span> | <a href="GetterLazy.html">Next feature (@Getter(lazy=true))</a><br /> <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2010 Reinier Zwitserloot and Roel Spilker, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> diff --git a/website/features/Log.html b/website/features/Log.html index 6912b6ed..c5d7771c 100644 --- a/website/features/Log.html +++ b/website/features/Log.html @@ -15,7 +15,7 @@ <div class="overview"> <h3>Overview</h3> <p> - You can annotate any field with <code>@Log</code> to let lombok generate a logger field automatically.<br /> + <em>NEW in lombok 0.10: </em>You can annotate any field with <code>@Log</code> to let lombok generate a logger field automatically.<br /> The logger is named <code>log</code> and field's type depends on which logger you have selected. </p><p> There are four <code>@Log</code> choices available:<br /> @@ -50,11 +50,16 @@ <h3>Small print</h3><div class="smallprint"> <p> If a field called <code>log</code> already exists, a warning will be emitted and no code will be generated. + </p><p> + A future feature of lombok's <code>@Log</code> is to find calls to the logger field and, if the chosen logging framework supports + it and the log level can be compile-time determined from the log call, guard it with an <code>if</code> statement. This way if + the log statement ends up being ignored, the potentially expensive calculation of the log string is avoided entirely. This does mean + that you should <em>NOT</em> put any side-effects in the expression that you log. </p> </div> </div> <div class="footer"> - <a href="index.html">Back to features</a> | <a href="SneakyThrows.html">Previous feature (@SneakyThrows)</a> | <span class="disabled">Next feature</span><br /> + <a href="index.html">Back to features</a> | <a href="SneakyThrows.html">Previous feature (@SneakyThrows)</a> | <a href="val.html">Next feature (val)</a><br /> <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009-2010 Reinier Zwitserloot, Roel Spilker and Robbert Jan Grootjans, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> diff --git a/website/features/ToString.html b/website/features/ToString.html index 23041f48..e350c265 100644 --- a/website/features/ToString.html +++ b/website/features/ToString.html @@ -66,7 +66,7 @@ </div> </div> <div class="footer"> - <a href="index.html">Back to features</a> | <a href="GetterSetter.html">Previous feature (@Getter / @Setter)</a> | <a href="EqualsAndHashCode.html">Next feature (@EqualsAndHashCode)</a><br /> + <a href="index.html">Back to features</a> | <a href="GetterLazy.html">Previous feature (@Getter(lazy=true))</a> | <a href="EqualsAndHashCode.html">Next feature (@EqualsAndHashCode)</a><br /> <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2009 Reinier Zwitserloot and Roel Spilker, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> </div> <div style="clear: both;"></div> diff --git a/website/features/index.html b/website/features/index.html index d216ddb4..edc173fb 100644 --- a/website/features/index.html +++ b/website/features/index.html @@ -15,6 +15,8 @@ <dl> <dt><a href="GetterSetter.html"><code>@Getter</code> / <code>@Setter</code></a></dt> <dd>Never write <code>public int getFoo() {return foo;}</code> again.</dd> + <dt><a href="GetterLazy.html"><code>@Getter(lazy=true)</code></a></dt> + <dd>Laziness is a virtue!</dd> <dt><a href="ToString.html"><code>@ToString</code></a></dt> <dd>No need to start a debugger to see your fields: Just let lombok generate a <code>toString</code> for you!</dd> <dt><a href="EqualsAndHashCode.html"><code>@EqualsAndHashCode</code></a></dt> @@ -32,6 +34,8 @@ <dd>To boldly throw checked exceptions where no one has thrown them before!</dd> <dt><a href="Log.html"><code>@Log</code></a></dt> <dd>Captain's Log, stardate 24435.7: "What was that line again?"</dd> + <dt><a href="val.html"><code>val</code></a></dt> + <dd>Finally! hassle-free final local variables.</dd> </dl> </div> <div class="pointer"> diff --git a/website/features/val.html b/website/features/val.html new file mode 100644 index 00000000..a3ce58e0 --- /dev/null +++ b/website/features/val.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html><head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <link rel="stylesheet" type="text/css" href="../logi/reset.css" /> + <link rel="stylesheet" type="text/css" href="features.css" /> + <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" /> + <meta name="description" content="Spice up your java" /> + <title>@Data</title> +</head><body><div id="pepper"> + <div class="minimumHeight"></div> + <div class="meat"> + <div class="header"><a href="../index.html">Project Lombok</a></div> + <h1>val</h1> + <div class="byline">Finally! hassle-free final local variables.</div> + <div class="overview"> + <h3>Overview</h3> + <p> + <em>NEW in Lombok 0.10: </em>You can use <code>val</code> as the type of a local variable declaration instead of actually writing the type. When you do this, + the type will be inferred from the initializer expression. The local variable will also be made final. This feature works + on local variables and on foreach loops only, not on fields. The initializer expression is required. + </p><p> + <em>WARNING: This feature does not currently work in NetBeans. We're working on fixing that.</em> + </p> + </div> + <div class="snippets"> + <div class="pre"> + <h3>With Lombok</h3> + <div class="snippet">@HTML_PRE@</div> + </div> + <div class="sep"></div> + <div class="post"> + <h3>Vanilla Java</h3> + <div class="snippet">@HTML_POST@</div> + </div> + </div> + <div style="clear: left;"></div> + <div class="overview"> + <h3>Small print</h3><div class="smallprint"> + <p> + For compound types, the most common superclass is inferred, not any shared interfaces. For example, <code>bool ? new HashSet() : new ArrayList()</code> + is an expression with a compound type: The result is both <code>AbstractCollection</code> as well as <code>Serializable</code>. The type inferred will be + <code>AbstractCollection</code>, as that is a class, whereas <code>Serializable</code> is an interface. + </p><p> + In ambiguous cases, such as when the initializer expression is <code>null</code>, <code>java.lang.Object</code> is inferred. + </p> + </div> + </div> + <div class="footer"> + <a href="index.html">Back to features</a> | <a href="Log.html">Previous feature (@Log)</a> | <span class="disabled">Next feature</span><br /> + <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright © 2010 Reinier Zwitserloot and Roel Spilker, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span> + </div> + <div style="clear: both;"></div> + </div> +</div> +<script type="text/javascript"> + var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); + document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); +</script> +<script type="text/javascript"> + try { + var pageTracker = _gat._getTracker("UA-9884254-1"); + pageTracker._trackPageview(); + } catch(err) {} +</script> +</body></html> |