Juan Zhong Juan Zhong - 3 years ago 287
Java Question

lombok @Builder(toBuilder = true) compilation error when used on constructor of a sub class

My code is as followd

package test.lombok;

import lombok.*;

@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class SuperClass {

private int foo;

@Getter
public static class SubClass extends SuperClass {

private int bar;

@Builder(toBuilder = true)
private SubClass(int foo, int bar) {
super(foo);
this.bar = bar;
}

}
}


As showed above, I'm trying to use @Builder(toBuilder = true) on a sub class.

When toBuilder set to false, there is no problem at all.

But when I set toBuilder = true, I got an compilation error "Error:java: foo has private access in test.lombok.SuperClass".

I'm wondering why does this happen and how to fix this.

Answer Source

The problem is because of how the toBuilder method is implemented in SubClass:

public SuperClass.SubClass.SubClassBuilder toBuilder() {
    return (new SuperClass.SubClass.SubClassBuilder()).foo(this.foo).bar(this.bar);
}

Instead of this.foo it should be super.foo, and the code would compile. Accessing super.foo is possible in this case because SubClass is an inner class of the SuperClass, otherwise, Java would disallow super.foo too.

If you want to see the code generated by lombok by for yourself, declare foo as public, then compile, then delombok (or decompile) and you will see code like this (then change the property to private to see where the error occurs):

import java.beans.ConstructorProperties;

public class SuperClass {
    public int foo;

    @ConstructorProperties({"foo"})
    protected SuperClass(int foo) {
        this.foo = foo;
    }

    public int getFoo() {
        return this.foo;
    }

    public static class SubClass extends SuperClass {
        private int bar;

        private SubClass(int foo, int bar) {
            super(foo);
            this.bar = bar;
        }

        public static SuperClass.SubClass.SubClassBuilder builder() {
            return new SuperClass.SubClass.SubClassBuilder();
        }

        public SuperClass.SubClass.SubClassBuilder toBuilder() {
            return (new SuperClass.SubClass.SubClassBuilder()).foo(this.foo).bar(this.bar);
        }

        public int getBar() {
            return this.bar;
        }

        public static class SubClassBuilder {
            private int foo;
            private int bar;

            SubClassBuilder() {
            }

            public SuperClass.SubClass.SubClassBuilder foo(int foo) {
                this.foo = foo;
                return this;
            }

            public SuperClass.SubClass.SubClassBuilder bar(int bar) {
                this.bar = bar;
                return this;
            }

            public SuperClass.SubClass build() {
                return new SuperClass.SubClass(this.foo, this.bar);
            }

            public String toString() {
                return "SuperClass.SubClass.SubClassBuilder(foo=" + this.foo + ", bar=" + this.bar + ")";
            }
        }
    }
}

EDIT: Thanks to @maaartinus for pointing me to super.foo, the answer is updated with that info.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download