javadynamic

Make dynamic method arguments during the compilation in Java


There is the big builder that is the heart of my project and that is used very frequently. I want to make every argument in every method dynamic (expect lambda expression as an agrument). Hovewer, I will need to create twice more methods (or even bigger amount), but my builder class is already too big and I don't want to waste my time, when I add another method to it.

I want to make something like lombok annotation to method to make methods able to receive Supplier<T> and T type argument at the same time. It should get value from the supplier, when it call some method, or get field from the object.

It should be something like

@DynamicArguments
public void randFunc(String string, Integer value) {
   // some code
}
randFunc("word", 1) // works
randFunc(() -> "123546", 3) // works
randFunc(() -> "123456", () -> 8) // works

I've tryed to research groovy and custom lombok annotations to do it, but it didn't help much.


Solution

  • I would use an arguments builder class.

    public static class RandFuncArgs {
        private Supplier<String> string;
    
        private IntSupplier value;
    
        public RandFuncArgs() {
            string("");
            value(0);
        }
    
        public RandFuncArgs(String s,
                            int value) {
            string(s);
            value(value);
        }
    
        public String getString() {
            return s.get();
        }
    
        public int getValue() {
            return value.getAsInt();
        }
    
        public RandFuncArgs string(String s) {
            return string(() -> s);
        }
    
        public RandFuncArgs string(Supplier<String> s) {
            this.string = Objects.requireNonNull(s, "Argument cannot be null.");
            return this;
        }
    
        public RandFuncArgs value(int value) {
            return value(() -> value);
        }
    
        public RandFuncArgs value(IntSupplier value) {
            this.value = Objects.requireNonNull(value, "Argument cannot be null.");
            return this;
        }
    }
    

    Now your outer class just needs one method:

    public void randFunc(RandFuncArgs args) {
        // ...
    }
    

    And others can call it as:

    obj.randFunc(new RandFuncArgs().string("word").value(1));
    obj.randFunc(new RandFuncArgs().string(() -> "123546").value(3));
    obj.randFunc(new RandFuncArgs().string(() -> "123456").value(() -> 8));