@Delegate

Overview

NEW IN Lombok 0.10: Any field or no-argument method can be annotated with @Delegate to let lombok generate delegate methods that forward the call to this field (or the result of invoking this method).

Lombok delegates all public methods of the field's type (or method's return type), as well as those of its supertype except for all methods declared in java.lang.Object.

You can pass any number of classes into the @Delegate annotation's types parameter. If you do that, then lombok will delegate all public methods in those types (and their supertypes, except java.lang.Object) instead of looking at the field/method's type.

All public non-Object methods that are part of the calculated type(s) are copied, whether or not you also wrote implementations for those methods. That would thus result in duplicate method errors. You can avoid these by using the @Delegate(excludes=SomeType.class) parameter to exclude all public methods in the excluded type(s), and their supertypes.

To have very precise control over what is delegated and what isn't, write private inner interfaces with method signatures, then specify these private inner interfaces as types in @Delegate(types=PrivateInnerInterfaceWithIncludesList.class, excludes=SameForExcludes.class).

With Lombok

01 import java.util.ArrayList;
02 import java.util.Collection;
03 
04 import lombok.Delegate;
05 
06 public class DelegationExample {
07   private interface SimpleCollection {
08     boolean add(String item);
09     boolean remove(Object item);
10   }
11   
12   @Delegate(types=SimpleCollection.class)
13   private final Collection<String> collection = new ArrayList<String>();
14 }
15 
16 
17 class ExcludesDelegateExample {
18   long counter = 0L;
19   
20   private interface Add {
21     boolean add(String x);
22     boolean addAll(Collection<? extends String> x);
23   }
24   
25   @Delegate(excludes=Add.class)
26   private final Collection<String> collection = new ArrayList<String>();
27   
28   public boolean add(String item) {
29     counter++;
30     return collection.add(item);
31   }
32   
33   public boolean addAll(Collection<? extends String> col) {
34     counter += col.size();
35     return collection.addAll(col);
36   }
37 }

Vanilla Java

01 import java.util.ArrayList;
02 import java.util.Collection;
03 
04 public class DelegationExample {
05   private interface SimpleCollection {
06     boolean add(String item);
07     boolean remove(Object item);
08   }
09   
10   private final Collection<String> collection = new ArrayList<String>();
11   
12   @java.lang.SuppressWarnings("all")
13   public boolean add(final java.lang.String item) {
14     return this.collection.add(item);
15   }
16   
17   @java.lang.SuppressWarnings("all")
18   public boolean remove(final java.lang.Object item) {
19     return this.collection.remove(item);
20   }
21 }
22 
23 class ExcludesDelegateExample {
24   long counter = 0L;
25   
26   private interface Add {
27     boolean add(String x);
28     boolean addAll(Collection<? extends String> x);
29   }
30   
31   private final Collection<String> collection = new ArrayList<String>();
32   
33   public boolean add(String item) {
34     counter++;
35     return collection.add(item);
36   }
37   
38   public boolean addAll(Collection<? extends String> col) {
39     counter += col.size();
40     return collection.addAll(col);
41   }
42   
43   @java.lang.SuppressWarnings("all")
44   public int size() {
45     return this.collection.size();
46   }
47   
48   @java.lang.SuppressWarnings("all")
49   public boolean isEmpty() {
50     return this.collection.isEmpty();
51   }
52   
53   @java.lang.SuppressWarnings("all")
54   public boolean contains(final java.lang.Object arg0) {
55     return this.collection.contains(arg0);
56   }
57   
58   @java.lang.SuppressWarnings("all")
59   public java.util.Iterator<java.lang.String> iterator() {
60     return this.collection.iterator();
61   }
62   
63   @java.lang.SuppressWarnings("all")
64   public java.lang.Object[] toArray() {
65     return this.collection.toArray();
66   }
67   
68   @java.lang.SuppressWarnings("all")
69   public <T extends .java.lang.Object>T[] toArray(final T[] arg0) {
70     return this.collection.<T>toArray(arg0);
71   }
72   
73   @java.lang.SuppressWarnings("all")
74   public boolean remove(final java.lang.Object arg0) {
75     return this.collection.remove(arg0);
76   }
77   
78   @java.lang.SuppressWarnings("all")
79   public boolean containsAll(final java.util.Collection<?> arg0) {
80     return this.collection.containsAll(arg0);
81   }
82   
83   @java.lang.SuppressWarnings("all")
84   public boolean removeAll(final java.util.Collection<?> arg0) {
85     return this.collection.removeAll(arg0);
86   }
87   
88   @java.lang.SuppressWarnings("all")
89   public boolean retainAll(final java.util.Collection<?> arg0) {
90     return this.collection.retainAll(arg0);
91   }
92   
93   @java.lang.SuppressWarnings("all")
94   public void clear() {
95     this.collection.clear();
96   }
97 }

Small print

When passing classes to the annotation's types or excludes parameter, you cannot include generics. This is a limitation of java. Use private inner interfaces or classes that extend the intended type including the generics parameter to work around this problem.

When passing classes to the annotation, these classes do not need to be supertypes of the field. See the example.

@Delegate cannot be used on static fields or methods.