N
Novice
I'm trying to understand the example on page 14 of Effective Java by Joshua
Bloch (Second Edition). I hope someone here can help.
Here's the code from the book for the sake of those who don't have the book
(or the same edition of the book):
=======================================================================
//Builder Pattern
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;
//Option 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) {
this.calories = val;
return this;
}
public Builder fat(int val) {
this.fat = val;
return this;
}
public Builder carbohydrate(int val) {
this.carbohydrate = val;
return this;
}
public Builder sodium(int val) {
this.sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.carbohydrate = builder.carbohydrate;
}
}=======================================================================
I should start by saying I have successfully imitated the example in my own
code. I'm just not entirely sure what it is doing.
Bloch clearly intends this technique as a way to avoid the confusion of
methods where you simply have a long list of parameters and could easily
enter parameters out of order. The code on page 15 shows how much clearer
things are when you use his technique; all of the optional parameters can
have clear names so that you know what each one is. I really like this; I
think it's MUCH better than simply listing a bunch of different integers
and hoping you assign each one to the right variable. In a nutshell, I get
what he is doing but I'm just not sure how this code works.
Questions:
1. I understand that a NutritionFacts could conceivably be just a
servingSize and a number of servings. All of the other values are optional
on an individual basis: any one or more of them could be there but don't
need to be. Any value that is omitted takes a default (of zero in this
example). But why are the methods calories(), fat(), carbohydrate() and
sodium() each returning Builder? They aren't constructors and they only
deal with one data value, fat or calories or whatever, but they apparently
return a complete Builder.
I'm also having trouble understanding some of the compiler warnings given
to me by Eclipse (3.7.1) when I actually code the class the way he has it:
- I get a "not used" warning for all of the private final variables in
NutritionClass (Eclipse offers to delete the variables OR create gettsrs
and setters OR "add @SuppressWarnings - unused" for each of them. I'm not
fond of any of these options but what is the best thing to do and why? Why
does Eclipse think they are unused when the NutritionFacts constructor is
clearly assigning values to them?
- I get "access to enclosing constructor NutritionFacts
(NutritionFacts.Builder) is emulated by a synthetic accessor method" in the
return statement of the build() method (Eclipse offers to remove the
"private" from the constructor for NutritionFacts OR to add
"@SuppressWarnings - synthetic access" to NutritionFacts but I'm not sure
which is better and why.
- I get "read access to enclosing field NutritionFacts.Builder.servingSize
is emulated by a synthetic accessor method" (Eclipse offers to remove the
"private" from the variables in Builder OR to add "@SuppressWarnings -
synthetic access" to NutritionFacts but I'm not sure which is better and
why.
Bloch (Second Edition). I hope someone here can help.
Here's the code from the book for the sake of those who don't have the book
(or the same edition of the book):
=======================================================================
//Builder Pattern
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;
//Option 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) {
this.calories = val;
return this;
}
public Builder fat(int val) {
this.fat = val;
return this;
}
public Builder carbohydrate(int val) {
this.carbohydrate = val;
return this;
}
public Builder sodium(int val) {
this.sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.carbohydrate = builder.carbohydrate;
}
}=======================================================================
I should start by saying I have successfully imitated the example in my own
code. I'm just not entirely sure what it is doing.
Bloch clearly intends this technique as a way to avoid the confusion of
methods where you simply have a long list of parameters and could easily
enter parameters out of order. The code on page 15 shows how much clearer
things are when you use his technique; all of the optional parameters can
have clear names so that you know what each one is. I really like this; I
think it's MUCH better than simply listing a bunch of different integers
and hoping you assign each one to the right variable. In a nutshell, I get
what he is doing but I'm just not sure how this code works.
Questions:
1. I understand that a NutritionFacts could conceivably be just a
servingSize and a number of servings. All of the other values are optional
on an individual basis: any one or more of them could be there but don't
need to be. Any value that is omitted takes a default (of zero in this
example). But why are the methods calories(), fat(), carbohydrate() and
sodium() each returning Builder? They aren't constructors and they only
deal with one data value, fat or calories or whatever, but they apparently
return a complete Builder.
I'm also having trouble understanding some of the compiler warnings given
to me by Eclipse (3.7.1) when I actually code the class the way he has it:
- I get a "not used" warning for all of the private final variables in
NutritionClass (Eclipse offers to delete the variables OR create gettsrs
and setters OR "add @SuppressWarnings - unused" for each of them. I'm not
fond of any of these options but what is the best thing to do and why? Why
does Eclipse think they are unused when the NutritionFacts constructor is
clearly assigning values to them?
- I get "access to enclosing constructor NutritionFacts
(NutritionFacts.Builder) is emulated by a synthetic accessor method" in the
return statement of the build() method (Eclipse offers to remove the
"private" from the constructor for NutritionFacts OR to add
"@SuppressWarnings - synthetic access" to NutritionFacts but I'm not sure
which is better and why.
- I get "read access to enclosing field NutritionFacts.Builder.servingSize
is emulated by a synthetic accessor method" (Eclipse offers to remove the
"private" from the variables in Builder OR to add "@SuppressWarnings -
synthetic access" to NutritionFacts but I'm not sure which is better and
why.