Calling multiple methods in Java

Mihai Neacsu picture Mihai Neacsu · Oct 27, 2011 · Viewed 34.1k times · Source

I found a new way of calling multiple methods in Java and I don't really understands what's happening behind:

public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;

public static class Builder {
    // Required parameters
    private final int servingSize;
    private final int servings;
    // Optional parameters - initialized to default values
    private int calories      = 0;
    private int fat           = 0;
    private int carbohydrate  = 0;
    private int sodium        = 0;
    public Builder(int servingSize, int servings) {
        this.servingSize = servingSize;
        this.servings    = servings;
    }
        public Builder calories(int val)
            { calories = val;      return this; }
        public Builder fat(int val)
            { fat = val;           return this; }
        public Builder carbohydrate(int val)
            { carbohydrate = val;  return this; }
        public Builder sodium(int val)
            { sodium = val;        return this; }
        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
}  

    private NutritionFacts(Builder builder) {
        servingSize  = builder.servingSize;
        servings     = builder.servings;
        calories     = builder.calories;
    }

}

Now the class is instantiated using this line, and here's where it gets confusing:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

It all makes sense till the NutritionFacts.Build(int, int), after that, what exactly is happening? Why do the calories, sodium, carbohydrate methods from Builder class need to return this? Where does that class adress go into?

Thank you!

Answer

Dave Newton picture Dave Newton · Oct 27, 2011

It doesn't "go into" anything.

These methods return a value. In this case, they return the current instance, this. That instance has methods, like calories() and carbohydrates().

foo.calories(12) returns the instance, and we can call its methods: foo.calories(12).sodium(35).

It's no different than the "return value" from the constructor, implicitly defined as the new instance. In this case it's normal methods, still returning an instance--the current one.

It's the same as this:

Builder foo = new Builder(1, 2); // The "return" value of a ctor is the reference, foo
foo.sodium(10);   // Returns foo, but we ignore it
foo.calories(42); // Returns foo, but we ignore it

(foo.sodium(10)).calories(42);
^^^^^^^^^^^^^^^^ foo, with the side effect of setting the sodium value

Here's an SO question with some good examples.