This question already has answers here:
How to avoid making long constructors [duplicate]
(3 answers)
Elegant alternatives for huge amount of arguments in class constructor [closed]
(4 answers)
Closed 7 years ago.
I have a builder pattern in which most likely all my parameters are going to be mandatory so I have created a long constructor as shown below in the code.
public final class ResponseHolder {
// all below six are related to response information
private final String response;
private final boolean isLinking;
private final TypeHold typeOfId;
private final long userTimeInMs;
private final long userLmdInDays;
private final String maskInfo;
// below two are related to error handling
private final ErrorCode error;
private final StatusCode status;
private ResponseHolder(Builder builder) {
this.response = builder.response;
this.isLinking = builder.isLinking;
this.typeOfId = builder.typeOfId;
this.userTimeInMs = builder.userTimeInMs;
this.userLmdInDays = builder.userLmdInDays;
this.maskInfo = builder.maskInfo;
this.error = builder.error;
this.status = builder.status;
}
public static class Builder {
protected final String response;
protected final TypeHold typeOfId;
protected final String maskInfo;
protected final ErrorCode error;
protected final StatusCode status;
protected final boolean isLinking;
protected final long userTimeInMs;
protected final long userLmdInDays;
public Builder(String response, TypeHold typeOfId, String maskInfo, ErrorCode error,
StatusCode status, boolean isLinking, long userTimeInMs, long userLmdInDays) {
this.response = response;
this.typeOfId = typeOfId;
this.maskInfo = maskInfo;
this.error = error;
this.status = status;
this.isLinking = isLinking;
this.userTimeInMs = userTimeInMs;
this.userLmdInDays = userLmdInDays
}
public ResponseHolder build() {
return new ResponseHolder(this);
}
}
// getters here
}
Now I am confuse when all the parameters are mandatory, then how it can be useful? Is there any better way of representing my above Builder pattern? May be logically grouping the parameters being passed in to their own classes to reduce the number of parameters being passed to the builder constructor?
While having separate objects simplifies things quite a bit, it also makes things a little difficult to follow if one is not familiar with the code. One thing I can do is moving all parameters into their own addParam(param) methods and then performing validation on required parameters in the build() method at runtime?
What is best practice I should follow here and is there any better approach that I can use here?
The Builder pattern shines when there are many different valid parameter permutations that allow you to create an object. Without the Builder pattern, you would be forced to create many ugly and confusing constructors to handle all the possible valid parameter combinations.
But in your case, there is only one valid set of parameters that allows you to create your object. This is exactly what a constructor is for. Using the Builder pattern here is not only overkill, it simply is not appropriate.
Just use a normal constructor for your ResponseHolder class.
The purpose of the builder pattern is to have a no-arg constructor, many well-named setter methods, and a final completion method, which validates that combination of values given are valid, before constructing the target object.
In your case, since all values are required, the main purpose of the builder pattern is to provide a form of named-parameter support.
Also, your target object should have many-arg constructor, rather than taking builder object as argument)
So, your builder should be (assuming no null values allowed):
public static class Builder {
private String response;
private TypeHold typeOfId;
private String maskInfo;
private ErrorCode error;
private StatusCode status;
private Boolean isLinking;
private Long userTimeInMs;
private Long userLmdInDays;
public Builder setResponse(String response) {
this.response = response;
return this;
}
public Builder setTypeOfId(TypeHold typeOfId) {
this.typeOfId = typeOfId;
return this;
}
public Builder setMaskInfo(String maskInfo) {
this.maskInfo = maskInfo;
return this;
}
public Builder setError(ErrorCode error) {
this.error = error;
return this;
}
public Builder setStatus(StatusCode status) {
this.status = status;
return this;
}
public Builder setIsLinking(boolean isLinking) {
this.isLinking = isLinking;
return this;
}
public Builder setUserTimeInMs(long userTimeInMs) {
this.userTimeInMs = userTimeInMs;
return this;
}
public Builder setUserLmdInDays(long userLmdInDays) {
this.userLmdInDays = userLmdInDays;
return this;
}
public ResponseHolder build() {
if (this.response == null ||
this.typeOfId == null ||
this.maskInfo == null ||
this.error == null ||
this.status == null ||
this.isLinking == null ||
this.userTimeInMs == null ||
this.userLmdInDays == null) {
throw new IllegalStateException("Not all required values given");
}
return new ResponseHolder(this.response,
this.typeOfId,
this.maskInfo,
this.error,
this.status,
this.isLinking,
this.userTimeInMs,
this.userLmdInDays);
}
}
You can now use it like this:
ResponseHolder holder = new ResponseHolder.Builder()
.setResponse(response)
.setTypeOfId(typeOfId)
.setMaskInfo(maskInfo)
.setError(error)
.setStatus(status)
.setIsLinking(isLinking)
.setUserTimeInMs(userTimeInMs)
.setUserLmdInDays(userLmdInDays)
.build();
Related
A view model that I'm working on has a method like:
public String getModelJson() {
final ItemModel model = this.getModel();
if (model == null) {
return StringUtils.EMPTY;
}
final GsonBuilder gsonBuilder = new GsonBuilder();
final Gson gson = gsonBuilder.create();
return gson.toJson(model);
}
This method relies on com.google.gson.Gson::toJson to serialize a POJO model to a JSON string that can be used in my view. Here's the model code:
public final class ItemModel extends ContentFragmentModel {
#Expose
private String error;
#Expose
private String id;
#Expose
private String name;
public ItemModel(final ContentFragment fragment) {
super(fragment);
}
public String id() {
return this.id;
}
public String name() {
return this.name;
}
#Override
protected String getModelPath() {
return "/path/to/model";
}
}
When I call getModelJson from my view, the method always returns {}, even though I can prove that the model is being loaded correctly; if I rewrite the method like this:
public String getModelJson() {
final ItemModel model = this.getModel();
return model != null ? "{\"name\": \"" + model.getName() + "\"}";
}
...it returns the expected output: {"name": "item name"}, where item name is the name correctly loaded from the fragment.
How can I get the model to serialize correctly?
I realized the problem. Here's the code for the base model class:
public abstract class ContentFragmentModel {
protected String error;
private boolean isValid = false;
public ContentFragmentModel(#NotNull final ContentFragment fragment) {
final String className = this.getClass().getSimpleName();
if (fragment == null) {
this.error = "No content fragment passed to " + className + ".";
return;
}
final String fragmentModelPath = FragmentUtil.getFragmentModelPath(
fragment
);
if (!fragmentModelPath.equals(this.getModelPath())) {
this.error = "Invalid content fragment passed to " + className + ".";
return;
}
this.loadElements(fragment);
this.isValid = true;
}
public #NotNull String getError() {
return StringUtils.defaultIfBlank(this.error, StringUtils.EMPTY);
}
public boolean isValid() {
return this.isValid;
}
protected abstract String getModelPath();
}
Notice that the base model class AND the model class have a member called error. In the base class, this member is protected. In the extended class, it's private. This apparently works in Java - the member in the child class hides the parent member - but this weird usage of class inheritance seems to break com.google.gson.Gson::toJson. There is no mention of this in the docs for that method so I'm adding a post here to hopefully save some poor soul a couple hours if they run into the same issue I had.
The fix for me was just to remove the error member from the extending class. I found that it wasn't even really used for anything, so I just deleted it. If you are running into this with a member that can't be simply deleted, you might try renaming it so it doesn't collide with the member in the base class.
This question already has answers here:
Elegant alternatives for huge amount of arguments in class constructor [closed]
(4 answers)
Closed 7 years ago.
I have a client library in which I am making http remote calls to my rest service and then I am returning List<DataResponse> back to the customer who is calling our library with the response I am getting from my REST service along with any errors if there are any wrapped around DataResponse object.
public class DataResponse {
private final String response;
private final boolean isLink;
private final TypeOfId idType;
private final long ctime;
private final long lmd;
private final String maskInfo;
// below are for error stuff
private final ErrorCode error;
private final StatusCode status;
// constructors and getters here
}
Here is my ErrorCode enum class:
public enum ErrorCode {
// enum values
private final int code;
private final String status;
private final String description;
// constructors and getters
}
And here is my StatusCode enum class:
public enum StatusCode {
SUCCESS, FAILURE;
}
As you can see in my DataResponse class I have lot of fields so basis on that I have a very long constructor and everytime when I make a DataResponse object I have a big line with new DataResponse(.......). In future I might have more fields but for now I only have these fields.
Is there any better way I can use to make a DataResponse object and then return back List<DataResponse> from my library?
Do not use the builder pattern right away. It is not for types with tons of required fields. It's for types with tons of optional fields.
Builders' required properties are specified via the constructor. You are not forced to define values using methods, which makes those values optional.
This leaves potential for your object being only partially constructed. Using a builder for this would be abuse of the design.
With that said, you should decompose your type. I'm not sure what lmd or ctime is, or really what a DataResponse is supposed to represent, so I cannot tell you in which way you should decompose. But I can tell you cohesion is what determines such.
isLink, maskInfo and idType could possibly be decomposed into a DataResponseDetails object:
class DataResponseDetails {
private boolean isLink;
private String maskInfo;
private TypeOfId idType;
public DataResponseDetails(boolean isLink, String maskInfo, TypeOfId idType) {
//...
}
}
Now your DataResponse could be composed of DataResponseDetails:
class DataResponse {
private DataResponseDetails details;
private String response;
//...
public DataResponse(DataResponseDetails details, String response, ...) {
//...
}
}
Feel your constructor requires too much still? Decompose more!
Maybe you can identify smaller logical groups of fields an move them into objects of an own class. Then you can assemble all these objects in your DataResponse objects.
As Joshua Bloch stated it in Item 2 of Effective Java 2nd Edition, you should consider using a builder pattern, as it is a best practice.
Here is what you code could look like using it :
public class DataResponse {
private final String response;
private final boolean isLink;
private final TypeOfId idType;
private final long ctime;
private final long lmd;
private final String maskInfo;
// below are for error stuff
private final ErrorCode error;
private final StatusCode status;
// constructors and getters here
public static class Builder {
private final String response;
private final boolean isLink;
private final TypeOfId idType;
private final long ctime;
private final long lmd;
private final String maskInfo;
// below are for error stuff
private final ErrorCode error;
private final StatusCode status;
public Builder reponse(final String response) {
this.response = response;
return this;
}
public Builder isLing(final boolean isLink) {
this.isLink = isLink;
return this;
}
public DataResponse builder() {
return new DataResponse(this);
}
...
}
private DataResponse(final Builder builder) {
this.response = builder.response;
this.isLink = builder.isLink;
}
}
and then do something as follow :
DataResponse response = new DataResponse.Builder().reponse(anyResponse).isLink(isLink).build();
I have recently learned Joshua Bloch's builder pattern for creating objects with many optional fields. I've been using something like it for years, but never used an inner-class until Bloch's book suggested it to me. I love it.
I understand that another thread may alter the bulider's configuration, before it's actually built (with build()), such that it may be necessary to re-validate all values in the constructor of the enclosing class. Below is an example of a builder class that optionally reverifies its data.
So my question is this: Assuming this is a robust enough design, when there are defaults for all values--knowing this class is a poor choice for using defaults--and when every set-attempt is validated, is this re-check necessary? Although it may be different, it would never be invalid. Is that correct?
(Although this design is manageable, it is certainly complicated by the potential need for re-verification. And, honestly, I never multi-thread, but I don't want to make my library unusable by people that do.)
Thank you for any advice.
/**
<P><CODE>java ReverifyBuilderInEnclosingCnstrXmpl</CODE></P>
**/
public class ReverifyBuilderInEnclosingCnstrXmpl {
public static final void main(String[] igno_red) {
//Don't reverify
ReverifyBuilderInEnclosingCnstrXmpl rvbdx = new ReverifyBuilderInEnclosingCnstrXmpl.Cfg().
name("Big Bird").age(6).build();
System.out.println(rvbdx.sName);
System.out.println(rvbdx.iAge);
//Do reverify
rvbdx = new ReverifyBuilderInEnclosingCnstrXmpl.Cfg().
reverifyInEnclosing().
name("Big Bird").age(6).build();
}
public final String sName;
public final int iAge;
/**
<P>Create a new <CODE>ReverifyBuilderInEnclosingCnstrXmpl</CODE> with defaults.</P>
**/
public ReverifyBuilderInEnclosingCnstrXmpl() {
//Does not reverify. No need.
this(new ReverifyBuilderInEnclosingCnstrXmpl.Cfg());
}
private ReverifyBuilderInEnclosingCnstrXmpl(ReverifyBuilderInEnclosingCnstrXmpl.Cfg rbdx_c) {
sName = rbdx_c.sName;
iAge = rbdx_c.iAge;
ReverifyBuilderInEnclosingCnstrXmpl.Cfg.zcibValues(rbdx_c, sName, iAge, "constructor");
}
public static class Cfg {
private String sName = null;
private int iAge = -1;
private boolean bReVrfy = false;
public Cfg() {
//Defaults
bReVrfy = false;
name("Broom Hilda");
age(127);
}
//Self-returning configuration...START
//No way to unset.
public Cfg reverifyInEnclosing() {
bReVrfy = true;
return this;
}
public Cfg name(String s_name) {
zcib_name(s_name, "name");
sName = s_name;
return this;
}
public Cfg age(int i_age) {
zcib_age(i_age, "age");
iAge = i_age;
return this;
}
//Self-returning configuration...END
//Validate config...START
public static final void zcibValues(ReverifyBuilderInEnclosingCnstrXmpl.Cfg rbdx_c, String s_name, int i_age, String s_clgFunc) {
try {
if(!rbdx_c.bReVrfy) {
return;
}
} catch(NullPointerException npx) {
throw new NullPointerException("zcibValues: rbdx_c");
}
zcib_name(s_name, s_clgFunc);
zcib_age(i_age, s_clgFunc);
}
public static final void zcib_name(String s_name, String s_clgFunc) {
if(s_name == null || s_name.length() == 0) {
throw new IllegalArgumentException(s_clgFunc + ": s_name (" + s_name + ") is null or empty.");
}
}
public static final void zcib_age(int i_age, String s_clgFunc) {
if(i_age < 0) {
throw new IllegalArgumentException(s_clgFunc + ": i_age (" + i_age + ") is negative.");
}
}
//Validate config...END
public ReverifyBuilderInEnclosingCnstrXmpl build() {
return (new ReverifyBuilderInEnclosingCnstrXmpl(this));
}
}
}
Firstly - the builder pattern is not inherently thread unsafe. I am not sure how you are concluding that it is. Each thread that intends to use the builder will create its own Builder object, populate it in Joshua Bloch's pragmatic and beautiful way and use it to construct the object. There are no static variables being affected anywhere in that mechanism, there is no thread unsafety unless you introduce it yourself.
Your concern about validation is - in my humble opinion - a gross pre-optimisation that produces hideously contrived and horribly bloated code. There is no reason to try to avoid validation just because you know the data is valid. Validation is almost always trivial and often takes little more that a few instructions. By bloating the class with these horrible static validation methods you are probably adding thousands of times more cpu cycles just to load this bloated code than you are saving by avoiding the validation.
Compare your contrived and bloated code with this lucid, succinct and patently correct and thread safe code and see what I mean:
public class Thing {
public final String name;
public final int age;
public Thing() {
this(new Thing.Builder());
}
private Thing(Thing.Builder builder) {
name = builder.name;
age = builder.age;
}
public static class Builder {
private String name = null;
private int age = -1;
public Builder() {
name("Broom Hilda");
age(127);
}
public Builder name(String name) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Thing.Builder.name (" + name + ") is null or empty.");
}
this.name = name;
return this;
}
public Builder age(int age) {
if (age < 0) {
throw new IllegalArgumentException("Thing.Builder.age (" + age + ") is negative.");
}
this.age = age;
return this;
}
public Thing build() {
return (new Thing(this));
}
}
}
You are misunderstanding the pattern on an architectural level: all data during construction is tied to the local thread and not to be exposed to any external handler. The very moment build is called, the now finalized set of parameters is passed to an immutable object, which then first should verify the validity of those parameters in the constructor, then either return the final object or throw an exception.
As long as you keep the builder parameters thread-local, you cannot cause any threading-issues. If you violate this rule, you should ask yourself if what you are doing is correct and/or how you could solve it in a more fine-grained way.
So if you in your example need to use the builder from different threads, the simplest and safest way is to create a new builder instance instead of doing it statically. If you worry about performance, ThreadLocal is your friend.
I saw sometime in the last month an implementation of Null Object pattern as what seemed like a Singleton field on a type. I can't really remember the approach though. I'm working on patterns and conscious of implementing them out of place.
From my mind I think it would be as follows but can I get a review on that?
public final class SearchCriteriaAnomalyFilter {
public static final SearchCriteriaAnomalyFilter NULL_INSTANCE;
private final T2AnomalyStatus status;
private final T2AnomalyType type;
private final boolean limitMaxOneAnomaly;
public SearchCriteriaAnomalyFilter(T2AnomalyStatus status, T2AnomalyType type,
boolean limitMaxOneAnomaly){
this.status = status;
this.type = type;
this.limitMaxOneAnomaly = Boolean.valueOf(limitMaxOneAnomaly);
}
private SearchCriteriaAnomalyFilter(){}
public static SearchCriteriaAnomalyFilter instanceOfNullObject(){
if (NULL_INSTANCE == null) {
NULL_INSTANCE = new SearchCriteriaAnomalyFilter();
}
return NULL_INSTANCE;
}
...
}
public static final SearchCriteriaAnomalyFilter NULL_INSTANCE = new SearchCriteriaAnomalyFilter();
public static SearchCriteriaAnomalyFilter instanceOfNullObject(){
return NULL_INSTANCE;
}
The rest of your code seemed fine.
The reason to use the above construct is that there is no need for a lazy initialization: the null-object won't change, nor does it need any special construction (as you properly implemented with the private constructor).
If I want to validate my input, should I make validation code as private helper methods or create a separate static helper class? Does the validation code increase the size of the object?
More Information
Let's say I have a class
import java.util.Vector;
public class Place {
private final double longitude;
private final double latitude;
private final String id;
private String address;
private String name;
private String types;
private String icon;
private String phoneNumber;
private String websiteUrl;
private int rating;
private Vector<Integer> challenges;
public static class Builder {
// required parameter
private final double longitude;
private final double latitude;
private final String id;
// optional parameter
private String address = "n/a";
private String name = "n/a";
private String icon = "n/a";
private String phoneNumber = "n/a";
private String websiteUrl = "n/a";
private String types = "n/a";
private Vector<Integer> challenges = new Vector<Integer>();
private int rating = 0;
public Builder(double longitude, double latitude, String id) {
assert(longitude >= -180.0 && longitude <= 180.0);
assert(latitude >= -90.0 && longitude <= 90.0);
this.longitude = longitude;
this.latitude = latitude;
this.id = id;
}
public Builder address(String address) {
this.address = address;
return this;
}
public Builder types(String types) {
this.types = types;
return this;
}
public Builder name(String name) {
this.name = name;
return this;
}
public Builder icon(String icon) {
this.icon = icon;
return this;
}
public Builder phoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public Builder websiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
return this;
}
public Builder builder(int rating) {
this.rating = rating;
return this;
}
public Place build() {
return new Place(this);
}
}
public Place(Builder builder) {
// required parameters
longitude = builder.longitude;
latitude = builder.latitude;
id = builder.id;
// optional parameters
address = builder.address;
types = builder.types;
name = builder.name;
icon = builder.icon;
phoneNumber = builder.phoneNumber;
websiteUrl = builder.websiteUrl;
rating = builder.rating;
challenges = builder.challenges;
}
public double getLongitude() {
return longitude;
}
public double getLatitude() {
return latitude;
}
public String getId() {
return id;
}
public void setAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
public String getTypes() {
return types;
}
public void setTypes(String types) {
this.types = types;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setIconUrl(String icon) {
this.icon = icon;
}
public String getIcon() {
return icon;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setWebsiteUrl(String websiteUrl) {
this.websiteUrl = websiteUrl;
}
public String getWebsiteUrl() {
return websiteUrl;
}
public void setRating(int rating) {
this.rating = rating;
}
public int getRating() {
return rating;
}
#Override
public String toString() {
return "(" + Double.toString(longitude) + ", " + Double.toString(latitude) + ")";
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Place other = (Place) obj;
if (id == null) {
if (other.id != null)
return false;
}
else if (!id.equals(other.id))
return false;
return true;
}
public Vector<Integer> getChallenges() {
return new Vector<Integer>(challenges);
}
public void addChallenges(Integer i) {
this.challenges.add(i);
}
public void showChallenges() {
for (Integer i : challenges) {
System.out.print(i + ", ");
}
}
}
If I have to validate address argument before setting it, where should I put the code for validating address in this case?
If you are talking just seeing if the entered String is formatted correctly or if the length is right, then you would use a private method. If you would on the other hand check if the address is correct (look it up on a map) or any more advanced stuff, it would make sense to create a AddressValidator interface and call it from that private method.
The reason for the private method being that you call this both from a constructor, setter or any other method that could suppy an address. The reason for the interface being that you might want to have e.g. an online / offline AddressValidator (MockAddressValidator, or one that calls a different class for each country etc).
As an AddressValidator could be reused in other classes, and to keep your code clean, I would create it as a top level interface + OnlineAddressValidator. This makes your class better readable as well. For full configurability, you might want to think about how you are going to supply the AddressValidator instance, e.g. through the constructor or one defined as a static final validator.
public interface AddressValidator {
static class AddressValidatorResult {
// some results, you might want to return some useful feedback (if not valid)
boolean isValid() {
throw new IllegalStateException("Method not implemented yet");
}
}
public static class AddressValidationException extends Exception {
private AddressValidationException(AddressValidatorResult result) {
// add some implementation
}
}
// don't throw ValidateException here, invalid addresses are normal for
// validators, even if they aren't for the application that uses them
AddressValidatorResult validateAddress(String address);
// don't throw ValidateException here, invalid addresses are normal for
// validators, even if they aren't for the application that uses them
}
public class DefaultAddressValidator implements AddressValidator {
public static class Params {
// some parameters for this specific validator
}
private final Params params;
public DefaultAddressValidator(Params params) {
// creates this validator
this.params = params;
}
#Override
public AddressValidatorResult validateAddress(String address) {
// perform your code here
// I don't like "return null" as it may lead to bugs
throw new IllegalStateException("Method not implemented yet");
}
}
// and use it like this
private void validateAddress(String address) throws AddressValidationException {
// e.g. field AddressValidator set in constructor
AddressValidatorResult result = addressValidator.validateAddress(address);
if (!result.isValid()) {
throw new AddressValidationException(result);
}
}
Should I make validation code as private helper methods or create a separate static helper class?
This totally depends on your context. It's impossible to say what should be the best design, without knowing what you are trying to realise.
After you edit: IMO, it is still not easy to tell you. If you only have to validate the address in one single point of your application (id: the setter method), I would validate it inside the setter method. If the input was invalid, I whould throw an IllegalArgumentException.
Does the validation code increase the size of the object?
However, the answer to your second question is No. To understand why, you have to know what Object Oriented Programming is.
Some references:
http://en.wikipedia.org/wiki/Object-oriented_programming
http://en.wikipedia.org/wiki/Class_(computer_science)
Should I make validation code as private helper methods or create a
separate static helper class?
It depends if you think that you'll need to reuse the same method also in another class for the same purpose(input validation) it is better write the method in a separate static helper class so you can reuse the method and maintain it easily.
If you write the same private helper method in several class each time that you need to make a changes you have to edit each method in each class, with a static helper class you change the code in one place only ...
Read about PropertyChangeListener and Bean Validation.
I tend to validate within the get() and set() methods wherever possible - calling external static methods for common tasks such as checking dates or cleaning input (i.e. to avoid sql injection)
If you only use (and are only ever going to use) the validation within one class, keep it as a private helper method. If in doubt, I tend to pull the functionality out into a static helper class. It makes very little difference to the amount of code, is no more effort to implement, and is much more flexible.
The short answer is: you should implement your validation code the way that your framework tells you to. Typically, this is a public method or an annotation. An interface could work too. If you add code, your class size will increase.
Data validation should be automatically called by your software's infrastructure. This helps to prevent programmers from forgetting to call the appropriate code. So, the methods should be public (an interface would work too).
Frameworks like Struts, Spring, Hibernate and have their own validation systems. Java EE leverages bean validation.
I recommend bean validation, because it performs validation regardless of the input source. When most people think of input validation, they think of data coming from the user e.g. HTTP Request, command console, Swing text field. Spring and Struts validation is often fine for those situations. But in long lived programs developed for enterprises, other data feeds often get introduced e.g. SQL database updates from another programs, database restoration after a crash, enterprise service bus, JMS.
That is why I prefer bean validation. The downside is that "safe sources" (data that you know is untainted) are validated unnecessarily. But with today's processing power, that should rarely be a significant concern.
Java EE Tutorial