Required arguments with a Lombok @Builder

前端 未结 9 2473
天涯浪人
天涯浪人 2020-12-12 15:17

If I add @Builder to a class. The builder method is created.

Person.builder().name(\"john\").surname(\"Smith\").build();

I have a requirem

相关标签:
9条回答
  • 2020-12-12 16:14

    This is my solution for the problem

    import lombok.Builder;
    import lombok.Data;
    import lombok.NonNull;
    
    @Data
    @Builder(builderMethodName = "privateBuilder")
    public class Person {
        @NonNull
        private String name;
        @NonNull
        private String surname;
        private int age;//optional
    
    public static Url safeBuilder() {
        return new Builder();
    }
    
    interface Url {
        Surname name(String name);
    }
    
    interface Surname {
        Build surname(String surname);
    }
    
    interface Build {
        Build age(int age);
        Person build();
    }
    
    public static class Builder implements Url, Surname, Build {
        PersonBuilder pb = Person.privateBuilder();
    
        @Override
        public Surname name(String name) {
            pb.name(name);
            return this;
        }
    
        @Override
        public Build surname(String surname) {
            pb.surname(surname);
            return this;
    
        }
    
        @Override
        public Build age(int age) {
            pb.age(age);
            return this;
        }
    
        @Override
        public Person build() {
            return pb.build();
        }
        }
    }
    

    inspired by this blog post:

    https://blog.jayway.com/2012/02/07/builder-pattern-with-a-twist/

    0 讨论(0)
  • 2020-12-12 16:16

    The simpliest solution is to add a @lombok.NonNull to all mandatory values. The Builder will fail to build the object when mandatory fields are not set.

    Here's a JUnit test to demonstrate the behavior of all combinations of final and @NonNull:

    import static org.junit.Assert.fail;
    
    import org.junit.Test;
    
    import lombok.Builder;
    import lombok.ToString;
    
    public class BuilderTests {
        @Test
        public void allGiven() {
            System.err.println(Foo.builder()
                .nonFinalNull("has_value")
                .nonFinalNonNull("has_value")
                .finalNull("has_value")
                .finalNonNull("has_value")
                .build());
        }
    
        @Test
        public void noneGiven() {
            try {
                System.err.println(Foo.builder()
                    .build()
                    .toString());
                fail();
            } catch (NullPointerException e) {
                // expected
            }
        }
    
        @Test
        public void nonFinalNullOmitted() {
            System.err.println(Foo.builder()
                .nonFinalNonNull("has_value")
                .finalNull("has_value")
                .finalNonNull("has_value")
                .build());
        }
    
        @Test
        public void nonFinalNonNullOmitted() {
            try {
                System.err.println(Foo.builder()
                    .nonFinalNull("has_value")
                    .finalNull("has_value")
                    .finalNonNull("has_value")
                    .build());
                fail();
            } catch (NullPointerException e) {
                // expected
            }
        }
    
        @Test
        public void finalNullOmitted() {
            System.err.println(Foo.builder()
                .nonFinalNull("has_value")
                .nonFinalNonNull("has_value")
                .finalNonNull("has_value")
                .build());
        }
    
        @Test
        public void finalNonNullOmitted() {
            try {
                System.err.println(Foo.builder()
                    .nonFinalNull("has_value")
                    .nonFinalNonNull("has_value")
                    .finalNull("has_value")
                    .build());
                fail();
            } catch (NullPointerException e) {
                // expected
            }
        }
    
        @Builder
        @ToString
        private static class Foo {
            private String nonFinalNull;
    
            @lombok.NonNull
            private String nonFinalNonNull;
    
            private final String finalNull;
    
            @lombok.NonNull
            private final String finalNonNull;
        }
    }
    
    0 讨论(0)
  • 2020-12-12 16:21

    If you need this functionality, you can customize the builder class by yourself and you can still add @Builder Annotation.

    @Builder
    public class Person {
    
        public static class PersonBuilder {
            private String name;
    
            private PersonBuilder() {
            }
    
            public PersonBuilder(final String name) {
                this.name = name;
            }
        }
    
        private static PersonBuilder builder() {
            return null; // or we can throw exception.
        }
    
        public static PersonBuilder builder(final String name) {
            return new PersonBuilder(clientId);
        }
    }
    
    0 讨论(0)
提交回复
热议问题