Parleys.com Search Index

Home | Devoxx | Devoxx'09
Title: Project Lombok: Bye Bye Boilerplate

Summary:
In this presentation, the developers of lombok, Reinier Zwitserloot and Roel Spilker, will show the audience what lombok is about, and how you can use it to eliminate boilerplate from your java code.

Description:
In this presentation, the developers of lombok, Reinier Zwitserloot and Roel Spilker, will show the audience what lombok is about, and how you can use it to eliminate boilerplate from your java code. For example, instead of writing out common boilerplate such as getters, setters, toString, equals, and hashCode implementations, you can use lombok's @Data annotation. Lombok hooks into your compiler and IDE so that their interpretation of your source includes these methods, while you never actually see any of them in your editor. For IDEs, this means that you get all the benefits, such as auto-completion, the methods show up in your outline views, and search tools such as 'go to declaration'continue to work. While most IDEs offer a feature to generate the boilerplate, this is little help when reading the resulting code, and such code is much harder to maintain.

Speaker(s): Roel Spilker Reinier Zwitserloot

Keyword(s): lombok framework javase annotations devoxx 2009 conference

Slide Content:
1) Project Lombok: Bye Bye Boilerplate http://projectlombok.org/d09
2) http://projectlombok.org/d09 www.devoxx.com
3) Reinier Zwitserloot - Founder & developer www.devoxx.com
4) Reinier Zwitserloot - Founder & developer www.devoxx.com Roel Spilker - Senior Developer & java trainer
5) 4207m
6) 4392m
7) DEMO www.devoxx.com
8) WHAT IS LOMBOK?
9)
10)
11)
12)
13)
14)
15) Safety Harness Rope Carabiners
16) @Getter and @Setter Never write public int getFoo() {return foo;} again.
17) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } }
18) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } } public int getAltitude() { return altitude; }
19) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } }
20) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } } public void setAltitude(int altitude) { this.altitude = altitude; }
21) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } }
22) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } }
23) @Getter and @Setter Never write public int getFoo() {return foo;} again. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; public class Mountain { @Getter @Setter private int altitude = 4392; @Setter(AccessLevel.PROTECTED) private String name; @Setter @NonNull private String country; @Override public String toString() { return String.format("%s (%d m)", getName(), getAltitude()); } } public void setCountry(@NonNull String country) { if (country == null) throw new NullPointerException("country"); this.country = country; }
24) @ToString No need to start a debugger to see your fields: Just let lombok generate a toString for you!
25) @ToString No need to start a debugger to see your fields: Just let lombok generate a toString for you! 01 import lombok.ToString; 02 03 @ToString 04 public class Gear { 05 private static final Logger LOGGER = getLogger(); 06 private String name; 07 private Material material = Material.HEMP; 08 private String[] category; 09 private int id; 10
26) @ToString No need to start a debugger to see your fields: Just let lombok generate a toString for you! 01 import lombok.ToString; 02 03 @ToString 04 public class Gear { 05 private static final Logger LOGGER = getLogger(); 06 private String name; 07 private Material material = Material.HEMP; 08 private String[] category; 09 private int id; 10 Gear(name="Rope", material=HEMP, category=[foo, bar])
27) @ToString No need to start a debugger to see your fields: Just let lombok generate a toString for you! 01 02 03 04 05 06 07 08 09 10 import lombok.ToString; @ToString(excludes="id") public class Gear { private static final Logger LOGGER = getLogger(); private String name; private Material material = Material.HEMP; private String[] category; private int id; } Gear(name="Rope", material=HEMP, category=[foo, bar])
28) @EqualsAndHashCode Equality made easy: Generates hashCode and equals implementations from the fields of your object.
29) @EqualsAndHashCode Equality made easy: Generates hashCode and equals implementations from the fields of your object. 01 02 03 04 05 06 07 08 09 10 import lombok.EqualsAndHashCode; @EqualsAndHashCode(exclude={"id", "equipment"}) public class Mountaineer { private String name; private double highestPoint; private List equipment; private int age; private long id; }
30) @EqualsAndHashCode Equality made easy: Generates hashCode and equals implementations from the fields of your object. 01 02 03 04 05 06 07 08 09 10 import lombok.EqualsAndHashCode; @EqualsAndHashCode(of={"id"}) public class Mountaineer { private String name; private double highestPoint; private List equipment; private int age; private long id; }
31) @Data All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields. You even get a free constructor to initialize your final fields!
32) @Data All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields. You even get a free constructor to initialize your final fields! 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 import import import import lombok.AccessLevel; lombok.Setter; lombok.Data; lombok.ToString; @Data public class Mountain { private final String name; private final int altitude; @Setter(AccessLevel.PACKAGE) private Country country; private final double latitude, longitude; @ToString(includeFieldNames=false) @Data(staticConstructor="of") public static class Goal { private final String name; private final T target; } }
33) @Data All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields. You even get a free constructor to initialize your final fields! 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 import import import import lombok.AccessLevel; lombok.Setter; lombok.Data; lombok.ToString; @Data public class Mountain { private final String name; private final int altitude; @Setter(AccessLevel.PACKAGE) private Country country; private final double latitude, longitude; @ToString(includeFieldNames=false) @Data(staticConstructor="of") public static class Goal { private final String name; private final T target; } }
34) @Data All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields. You even get a free constructor to initialize your final fields! 01 import lombok.AccessLevel; 02 import lombok.Setter; 03 import lombok.Data; 04 import lombok.ToString; 05 06 @Data public class Mountain { 07 private final String name; 08 private final int altitude; 09 @Setter(AccessLevel.PACKAGE) Goal private Goal.of("Devoxx Audience Size", 1000); goal = Country country; 10 11 private final double latitude, longitude; 12 13 @ToString(includeFieldNames=false) 14 @Data(staticConstructor="of") 15 public static class Goal { 16 private final String name; 17 private final T target; 18 } 19 }
35) @Cleanup Automatic resource management: Call your close() methods safely with no hassle.
36) @Cleanup Automatic resource management: Call your close() methods safely with no hassle. 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 import lombok.Cleanup; import java.io.*; public class MountainStore { public void save(File file) throws IOException { @Cleanup InputStream in = getClass().getResourceAsStream( "mountains.dat"); @Cleanup OutputStream out = new FileOutputStream(file); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } }
37) 01 import java.io.*; 02 03 public class MountainStore { 04 public void save(File file) throws IOException { 05 InputStream in = getClass().getResourceAsStream( 05 "mountains.dat"); 06 try { 07 OutputStream out = new FileOutputStream(file); 08 try { 09 byte[] b = new byte[10000]; 10 while (true) { 11 int r = in.read(b); 12 if (r == -1) break; 13 out.write(b, 0, r); 14 } 15 } finally { 16 out.close(); 17 } 18 } finally { 19 in.close(); 20 } 21 } 22 }
38) 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 import lombok.Cleanup; import java.io.*; public class MountainStore { public void save(File file) throws IOException { @Cleanup InputStream in = getClass().getResourceAsStream( "mountains.dat"); @Cleanup OutputStream out = new FileOutputStream(file); byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } }
39) @Synchronized synchronized done right: Don't expose your locks.
40) @Synchronized synchronized done right: Don't expose your locks. 01 public class Flag { 02 private static TreeSet flags; 03 04 public synchronized static int getHighest() { 05 return flags.last().getAltitude(); 06 } 07 08 public synchronized void plant(Mountain mountain) { 09 mountain.plant(this); 10 System.out.println("top of the world!"); 11 } 12 }
41) @Synchronized synchronized done right: Don't expose your locks.
42) 01 public class Flag { 02 private static final Object $LOCK = new Object[0]; 03 private final Object $lock = new Object[0]; 04 02 private static TreeSet flags; 03 04 public static int getHighest() { 06 synchronized($LOCK) { 05 return flags.last().getAltitude(); 06 } 06 } 07 08 public void plant(Mountain mountain) { 06 synchronized($lock) { 09 mountain.plant(this); 10 System.out.println("top of the world!"); 11 } 11 } 12 }
43) 01 import lombok.Synchronized; 02 03 public class Flag { 04 private static TreeSet flags; 05 06 @Synchronized 07 public static int getHighest() { 08 return flags.last().getAltitude(); 09 } 10 11 @Synchronized 12 public void plant(Mountain mountain) { 13 mountain.plant(this); 14 System.out.println("top of the world!"); 15 } 16 }
44) @SneakyThrows To boldly throw checked exceptions where no one has thrown them before!
45) @SneakyThrows To boldly throw checked exceptions where no one has thrown them before! 01 import lombok.SneakyThrows; 02 03 public class SneakyThrowsExample implements Runnable { 04 05 public static String utf8ToString(byte[] bytes) { 06 return new String(bytes, "UTF-8"); 07 } 08 09 10 public void run() { 11 throw new Throwable(); 12 } 13 }
46) @SneakyThrows To boldly throw checked exceptions where no one has thrown them before! 01 import lombok.SneakyThrows; 02 03 public class SneakyThrowsExample implements Runnable { 04 @SneakyThrows(UnsupportedEncodingException.class) 05 public static String utf8ToString(byte[] bytes) { 06 return new String(bytes, "UTF-8"); 07 } 08 09 @SneakyThrows 10 public void run() { 11 throw new Throwable(); 12 } 13 }
47)
48)
49)
50)
51)
52)
53)
54)
55)
56)
57) class MountainStore implements Iterable { @Delegate Iterable mountains; public MountainStore() { this(Collections.emptyList()); } public MountainStore(List mountains) { this.mountains = mountains; } public static void main(String[] args) { MountainStore store = new MountainStore(); for (Mountain mountain : store) { System.out.println(mountain); } } }
58) @Mixin(RelativeOperations.class) @Data class Mountain implements Comparable { private final String name; private final int altitude; public int compareTo(Mountain m) { return altitude.compareTo(m.altitude); } public static void main(String[] args) { Mountain raoul = new Mountain("Raoul", 4207); Mountain rainier = new Mountain("Rainier", 4392); System.out.println(rainier.isGreaterThan(raoul)); } }
59) class Literals { private static final Pattern WIN_PATH = /[A-Z]:\(.*\)*/i; private static final String MESSAGE = """ Can’t find configuration file. You need to check: - If your computer is connected to the network - If the file Z:\mountains\mountains.dat exists"""; }
60) import java.util.Collections.sort extends java.util.List; class MountainStore { public static void main(String[] args) { List mountainNames = new ArrayList(Arrays.asList("Raoul", "Rainier")); System.out.println(mountainNames.sort()); } }
61)
62) public class Climber { private final List mountainsClimbed; public List climbedAbove(int altitude) { return [Mountain m : mountainsClimbed where(m.getAltitude() > altitude) select(m.getName())]; } }
63)
64) DEMO www.devoxx.com
65) http://projectlombok.org
(c) Parleys.com NV, 2006-2010 - Technical Info