I'm doing a basic Java course and I came to a problem: How do I create an object only if I have passed valid parameters to the Constructor?
Should I make an alternate class and call the constructor from there after the validation is realized?
Or should/could I use a static method in the class for the validation?
What is the best practice in this case?
The standard practice is to validate the arguments in the constructor. For example:
class Range {
private final int low, high;
Range(int low, int high) {
if (low > high) throw new IllegalArgumentException("low can't be greater than high");
this.low = low;
this.high = high;
}
}
Side note: to verify that arguments are not null, which is fairly common, you can use:
import static java.util.Objects.requireNonNull;
Constructor(Object o) {
this.o = requireNonNull(o); //throws a NullPointerException if 'o' is null
}
UPDATE
To reply to your specific comment about social security number. One way would be to add a method to the class:
//constructor
public YourClass(String ssn) {
if (!isValidSSN(ssn)) throw new IllegalArgumentException("not a valid SSN: " + ssn);
this.ssn = ssn;
}
public static boolean isValidSSN(String ssn) {
//do some validation logic
}
The calling code could then look like:
String ssn = getSsnFromUser();
while(!YourClass.isValidSSN(ssn)) {
showErrorMessage("Not a valid ssn: " + ssn);
ssn = getSsnFromUser();
}
//at this point, the SSN is valid:
YourClass yc = new YourClass(ssn);
With that design, you have achieved two things:
you validate the user input before using it (which you should always do - users are very good at typos)
you have made sure that if YourClass is misused an exception is thrown and it will help you detect bugs
You could go further by creating a SSN class that holds the SSN and encapsulates the validation logic. YourClass would then accept a SSN object as an argument which is always a valid SSN by construction.
I'd just throw an IllegalArgumentException in the constructor itself:
public class MyClass {
private int i;
public MyClass (int i) {
// example validation:
if (i < 0) {
throw new IllegalArgumentException ("i mustn't be negatve!");
}
this.i = i;
}
A well-known truism in programming is 'Don't use Exceptions for flow control'. Your code should be aware of the restrictions and guard against them before calling the constructor rather than handling errors. Exceptions exist for expectational circumstances, especially ones that cannot be predicted or guarded against (for example, an IO stream may become invalid during writing, despite being OK during a previous check).
While you can throw exceptions in your constructor, this is not always ideal. If you are writing public objects that you expect to be used/reused by others, Exceptions are the only real option for public constructors, however such limitations and their result (e.g. what exception will be thrown) should be clearly documented in the javadoc for the class.
For internal classes, assertions are more appropriate. As Oracle states: "Assertions... should be used to check for cases that should never happen, check assumptions about data structures, or enforcing constraints on arguments of private methods."—Using Assertions in Java Technology. You probably should still document your expectations for the class, but your application should internally do any checks beforehand rather than relying on any Exceptions being thrown.
Static factory methods can help a little, their benefits are elaborating upon a bit by another question: How to use “Static factory methods” instead of constructors. However, they don't give strong validation options without, again, relying on Exceptions when things are not valid (that, or returning null, which is less informative).
Your ideal solution is the Builder pattern. Not only does it allow for a greater deal of flexibility in managing your arguments, you may validate each one individually, or have a validate method that can evaluate all the fields at once. A builder can and should be used to hide the object's actual constructor, enjoying sole access to it and preventing any unwanted values from ever being submitted, while assertions can guard against 'the builder should never submit these values'.
Constructors can throw exceptions (see Can constructors throw exceptions in Java?) so you can have your constructor throwing an exception if invalid values are passed. You can also make your constructor private and use the static method to create your object, that performs the checks. This might be cleaner.
One way to make sure you have valid parameters passed to the constructor is to create the parent class with constructors that only accept the parameters you require, then create a subclass that your end-users use. If you force your user to call super() and pass in your required parameters, then they have to at least pass in the right data objects. As far as valid values for those parameters, that's up to you whether you want to include validation in the parent class constructor and throw runtime exceptions or whatnot.
Here's an example of the superclass / subclass thing. Let's call the superlcass SomeShape and the subclass Triangle. For any SomeShape object, you are going to force the "user" to provide a number of sides and a side length. This is how...
public class SomeShape {
private int numSides;
private int sideLength;
public SomeShape(int mNumSides, int mSideLength) {
numSides = mNumSides;
sideLength = mSideLength;
}
}
public class Triangle extends SomeShape {
private int height;
public Triangle(int mNumSides, int mSideLength, int mHeight) {
super(mNumSides, mSideLength);
height = mHeight;
}
}
Aside from hard-coding a bunch of logic and exception throwing into your constructor, this is a relatively clean way to enforce what parameters are required to create the object.
If you don't want to throw an exception from the constructor, you could make the constructor private and create a static method that returns a new instance of the object, or null if the arguments are invalid. The caller of this method would have to check if the result is null or not, however.
Example:
public class Foo {
private Foo(int arg1, Bar arg2) {
// guaranteed to be valid.
}
public static Foo construct(int arg1, Bar arg2) {
// perform validation
if (arg1 < 0 || arg2 == null) {
return null;
} else {
return new Foo(arg1, arg2);
}
}
}
Usage
Foo object = Foo.construct(1, new Bar());
if (object == null) {
// handle error here.
}
It's bad practice to throw an exception out of a constructor. You end up with a partially initialized object, which is probably going to break all kinds of contracts.
If a constructor isn't valid for all combinations of inputs, it's cleaner to create a factory method that does the validation, and make the constructor private. If there's a real possibility of failure (that is, the failure isn't due to a programming error), then it might be appropriate to return an Optional.
Related
I have a class Natural with a precondition before the constructor method (notice the requires).
public class Natural {
private int data;
#Requires("n != null")
public Natural(Natural n) {
this(n.data);
}
}
This is the test for that Precondition. It tests the constructor for a null input.
#Test(expected = PreconditionError.class)
public void testConstructorWrong2() {
Natural n = new Natural(null);
}
The test should pass, because this test expects a violation of the Precondition. But I am getting NullPonterException instead.
As stated on the Cofoja page:
However, a very important distinction is that constructor preconditions are checked after any call to a parent constructor. This is due to super calls being necessarily the first instruction of any constructor call, making it impossible to insert precondition checks before them. (This is considered a known bug.
The above probably applies to this as well as super. The #Requires condition can only be checked after the call to this(n.data); because Java won't allow anything to come before it. And so, the call to n.data throws a NullPointerException before the annotation even has a chance to check the precondition.
If you still want to check the precondition, you will have to remove the call to this(...) and initialize the object directly
#Requires("n != null")
public Natural(Natural n) {
this.data = n.data;
}
I wrote the below code, and as you see, in the constructor I call some methods to perform certain operations. And now what I am inquiring about is, whether it is a good practice to call those methods from the constructor OR declare those methods as public and instantiate an object from the class info, and let the object call those methods? What is the good practice for that?
Code:
class Info {
public RoadInfo(String cityName, double lat, double lng) throws FileNotFoundException, SAXException, IOException, XPathExpressionException {
// TODO Auto-generated constructor stub
this.cityname = cityName;
this.lat = lat;
this.lng = lng;
this.path = "c:"+File.separatorChar+this.cityname+".xml";
System.out.println(path);
this.initXPath();
this.method1()
this.method2()
..
this.expr = "//node[#lat='"+this.lat+"'"+"]/following-sibling::tag[1]/#v";
this.xPath.compile(this.expr);
String s = (String) this.xPath.evaluate(this.expr, this.document, XPathConstants.STRING);
System.out.println(s);
}
TLDR In my opinion, using methods inside of a constructor is a sign of bad design. If you aren't looking for design advice, then the answer "no there's nothing wrong with it, technically speaking, as long as you avoid calling non-final methods" should do you fine. If you ARE looking for design advice, see below.
I think your example code is not good practice at all. In my opinion, a constructor should only receive values which is relevant to it and should not need to perform any other initialization on those values. There's no way for you to test that your constructor 'works' with all of those little extra steps - all you can do is construct the object and hope that everything ends up in the correct state. Further, your constructor ends up with more than one reason to change, which violates the SRP.
class Info {
public RoadInfo(String cityName, double lat, double lng) throws FileNotFoundException, SAXException, IOException, XPathExpressionException {
// TODO Auto-generated constructor stub
this.cityname = cityName;
this.lat = lat;
this.lng = lng;
this.path = "c:"+File.separatorChar+this.cityname+".xml";
System.out.println(path);
this.initXPath();
this.method1()
this.method2()
..
this.expr = "//node[#lat='"+this.lat+"'"+"]/following-sibling::tag[1]/#v";
this.xPath.compile(this.expr);
String s = (String) this.xPath.evaluate(this.expr, this.document, XPathConstants.STRING);
System.out.println(s);
}
So, for example, this constructor is loading a file, parsing it in XPath.. if I ever want to create a RoadInfo object, I can now only do it by loading files and having to worry about exceptions being thrown. This class also now becomes hilariously difficult to unit test because now you can't test the this.initXPath() method in isolation, for example - if this.initXPath(), this.method1() or this.method2() have any failures, then every one of your test cases will fail. Bad!
I would prefer it to look something more like this:
class RoadInfoFactory {
public RoadInfo getRoadInfo(String cityName, double lat, double lng) {
String path = this.buildPathForCityName(cityName);
String expression = this.buildExpressionForLatitute(lat);
XPath xpath = this.initializeXPath();
XDocument document = ...;
String s = (String) xpath.evaluate(expression, document, XPathConstants.STRING);
// Or whatever you do with it..
return new RoadInfo(s);
}
}
Never mind the fact that you have at least 5 responsibilities here.
Build OS-neutral path
Build XPath expression for latitude/longitude
Create XPath doocument
Retrieve s - whatever that is
Create new RoadInfo instance
Each of these responsibilities (Except the last) should be separated into their own classes (IMO), and have RoadInfoFactory orchestrate them all together.
The purpose of the constructor is to establish the class invariants, that is, to bring the newly created object into a state that then allows clients to use them. In general, it is bad practice for an object to be relying on extra initialisation after it's constructed. What you want to avoid is to write such things into the documentation as:
...after creating an instance of class X, remember to ALWAYS call
initX(), or bad things will happen!
Though in certain cases it's difficult to avoid it and the constructor can become quite messy. For example loading external files in a constructor is problematic.
In these cases there are two things you can do:
Rewrite your constructor so it requires the contents of the file instead of the name. Let the caller do the loading. The main difference is that you require the caller to do something before the object is created, and you can express it with the signature of your constructor: public RoadInfo(String cityName, Document cityDatabase, double lat, double lng) {...} Of course you can go even further and require the value of s straight away and let the caller do the XPath search. Note that all these steps move the class towards having a single responsibility, which is considered a good thing.
But now you require the caller to perform many steps before they can build your RoadInfo. This is where you can use factories, which perform this extra initialisation too and return fully built RoadInfo objects.
The most important thing though is that the constructor must not call any method of the object under construction that can be overridden. Calling private methods is fine, calling public methods on this is not a good idea unless the methods or the class itself is marked as final.
If you call such a method, there's always a chance that the class overriding the method does something that breaks your functionality, like exposing this to the outside world before the construction is completed. Here's an example:
public abstract class Foo {
public Foo(String param) {
if (this.processParam(param) == null)
throw new IllegalArgumentException( "Can't process param.");
}
protected abstract processParam(String param);
}
public class Bar extends Foo {
public Bar(String param) {super(param);}
protected processParam(String param) {
SomeOtherClass.registerListener(this); // Things go horribly wrong here
return null;
}
}
If you now call new Bar("x"), the constructor of Foo will throw an exception because it considers the parameter invalid. But Bar.processParam() leaked a reference of this to SomeOtherClass, potentially allowing SomeOtherClass to use the Bar instance that shouldn't even exist.
More typically, classes requiring heavy initialization would be provided to the client via a factory method. Constructors are often too restrictive—a random example being the inability to surround the super or this opening call with try-catch.
If you provide a public factory method, you can make the constructor private. The constructor can only do the easy work like assigning final fields, and the factory takes over. In the long run this is a more future-proof design. Many public libraries had to break their earlier API to introduce factories that allow their code to grow.
Is it a good practice to call some methods from the constructor?
Sadly the only good answer to this is It depends on the object.
If the object is intended to hold information then the answer must be probably not, try to avoid it because an object should really only do one thing.
If, however, the object is there to perform a function then by all means make sure that it is ready to perform that function by calling methods etc. If, for example it is a database connection then you might wish to connect to the database at construct time, or at least register itself in a connection pool.
It is, however, good practice to postpone any potentially slow stuff you can postpone until you need it. In my example of the database you may wish to postpone the actual connection to the database but you would certainly register the connection in the connection pool.
Sadly - the answer to the opposite question:
Is it a bad practice to call some methods from the constructor?
Is also It depends on the object for similar reasons.
There's no good practice, just bad practice that you should not do.
When you call a method within a constructor, some dangerous here are:
1) the method can be overwritten, and its subclass implement break your class's constraint protected by constructor, the implement is out of your control.
class T {
int v;
T() {
v = getValue();
}
int getValue() {
return 1;
}
}
class Sub extends T {
#Override
int getValue() {
return -1;
}
}
here T's v suppose to be 1 when you call new T(), but when you create a new Sub(), 'v' will be set to -1, which may break T's constraint, and this happens unconsciously.
2) the half-constructed object leaked, while it's status may be illegal.
class T {
int a, b;
T(C c) {
// status of "this" is illegal now, but visible to c
c.calc(this);
a = 1;
b = 2;
}
}
class C {
int calc(T t) {
return t.a / t.b;
}
}
3) something more I don't know...
if you can prevent all of them, you can do what you want.
(Try to keep exceptions not thrown. So the constructor can nicely initialize a field.)
Do not call overridable methods in the constructor.
About the pitfalls of an overridable method call in a constructor:
The evaluation of a (child) constructor is:
"Zero" all fields (0, null, 0.0, false)
Call the super constructor (implicit if not in code)
Call all field initializations (field declarations with = ...)
Do rest of constructor code
So:
class A {
A() { f(); }
protected void f() { }
}
class B implements A {
String a;
String b = null;
String c = "c";
B() {
//[ a = null, b = null, c = null; ]
//[ super();
// B.f();
//]
//[ b = null; ]
//[ c = "c"; ]
// "nullA" - null - "c"
System.out.printf("end %s - %s - %s%n", a, b, c);
}
#Override
protected void f() {
System.out.printf("enter f : %s - %s - %s%n", a, b, c);
// null - null - null
a += "A";
b += "B";
c += "C";
// "nullA" - "nullB" - "nullC"
System.out.printf("leave f : %s - %s - %s%n", a, b, c);
}
}
That behavior is quite muddying the waters, and here doing assignments that are immediately overwritten by field initializations.
A normal call one often sees in constructors is a setter, that maybe has some normalization code. Make that setter public final void setX(X x);.
I'm reading about invariants, and I'm not sure I understood it completely. From Wikipedia,
The class invariant constrains the state stored in the object.
So, if I got it right, invariants don't apply to stateless objects because there are no constraints. Is that correct? Am I wrong? Am I comparing apples to oranges?
Stateless object doesn't have any state. Take an example of say utility class which doesnt have any field or has constant fields like below:
public class MyClass {
public static final int number = 1;
private final int count = 1;
}
This means that number/count will not change and will remain consistent irrespective of being referred by 'n' number of threads.
While if i take a class with say private field and is being say accessed by setter/getter then it will look like:
public class MyInvariantClass {
private int number;
public int getNumber() {
return number;
}
public void incrNumber() {
this.number++;
}
public void setNumber() {
this.number = number;
}
}
This class MyInvariantClass, has a state with number field. Think of this object being passed to multiple threads. Some may increment it, some may set it. Does it guarantee that number which we are using never goes out of int range and there by defaulting to negative? So here we fail to maintain invariant of integer when overflow occurs.
The invariant would be something like:
myBankAccount.Balance >= 0 between calls to any of the object's (mybankAccount) methods. The Balance variable is a member of the myBankAccount object.
If we have a stateless object, i.e. an object without any data members associated with it, then we can't really define an invariant (what would we define it on?).
A stateless class has no instance members, and therefore there is no state to keep valid.
From wikipedia:
In computer science, an invariant is a condition that can be relied
upon to be true during execution of a program, or during some portion
of it.
In java, these conditions (invariants) can be programmed into your code in a few ways. Here are some:
using the final keyword
using asserts
throwing exceptions
using mutator methods
For example, take the class Age:
public class Age {
private final int age;
public Age(int age) {
// Use exceptions...
if (age < 1) {
throw new IllegalArgumentException("Age cannot be less than 1");
}
// Or use assertions...
assert age > 0;
this.age = age;
}
// A method can be a invariant as well, because it makes sure
// member variables cannot be set to an invalid state.
public Age changeAge(int age) {
assert age > 1;
return new Age(age);
}
}
So, the final keyword is a compiler-time invariant because it makes sure the variable is not reassigned. The exception and assertion in the constructor are runtime invariants because they constrain age and make sure age is greater than 0. The public method is an invariant as well, because it asserts if it's argument is invalid.
Some languages have the concept of invariants built right in. On the wikipedia page you linked to, they list D and Eiffel as examples. What this means is that instead of raising exceptions, asserting and checking conditions, you can define a constraint (invariant) in one place, and the language has support to make sure that the instance variables remain within the constraints you set. In java, you must do this 'manually'.
public abstract class A {
private int result=-1;
public void final doExecuteMySpecialAlgorithm() {
result=0;
//do something here and get a new result
//it won't be -1.
}
public int getResult() {
if(result==-1)
throw new RuntimeException("Invoke my special algorithm first!");
return result;
}
}
Isn't getResult method a bad design - It is forcing user to invoke another method before it is invoked? How would you workaround this? Would your rather return -1 or say null (in case of an object type) and let the caller figure out what to do will a null return? or if you are sure that it won't be null, but for the return to be not null, you would have to invoke another method before invoking getResult method, would you just throw a RuntimeException? (or a checked exception?)
There's two ways here. Either make it synchronous (i.e. doExecuteMySpecialAlgorithm actually returns the result) or asynchronous.
The first is obvious, the second can be accomplished by returning a Future object for example. Either way, the caller doesn't need to think which is the proper order to call methods.
In some cases it may be alright to enforce the calling order of methods (such as the doFinal method in crypto classes), but you should still avoid making the code in a way that the user has to think carefully about how he's going to call your methods. Obviously he needs to know what to call, but if he needs to call 5 methods in a specific order, it probably means there should be only 1 method.
I mean after all, if you want to force the caller to call method1(), method2(), method3() in order, you should really make him call method(), which inside calls private methods method1(), method2() and method3(). That way you have the code well structured, but the caller can't fudge things up by calling the methods in the wrong order.
In your example I'd do the following:
public abstract class A {
private int result=-1;
public void final doExecuteMySpecialAlgorithm() {
result=0;
//do something here and get a new result
//it won't be -1.
}
public int getResult() {
if(result==-1)
doExecuteMySpecialAlgorithm();
return result;
}
}
This way a user can do the 'special' algorithm first, or if they 'forget' to, you (as the API writer) catch it for them and do this (instead of throwing an error).
Doing this makes your object do the work for you (object oriented design), of course this is YOUR API design, and I would assume that there would be extensive documentation dictating that if I call getResult that I must first call doExecuteMySpecialAlgorithm ... whatever you choose to implement YOU must document that the user is ordered to call function X before function Y or undefined behavior might result (or throw an error).
I've recently discovered an interesting way to create a new instance of an object in Google Guava and Project Lombok: Hide a constructor behind a static creator method. This means that instead of doing new HashBiMap(), you do HashBiMap.create().
My question is why? What advantage do you have of hiding the constructor? To me I see absolutely no advantage of doing this, and it seems to break basic object creation principles. Since the beggining you create an object with new Object(), not some Object.createMe() method. This almost seems like creating a method for the sake of creating a method.
What do you gain from doing this?
There are a number of reasons why you might prefer a static factory method instead of a public constructor. You can read Item 1 in Effective Java, Second Edition for a longer discussion.
It allows the type of the object returned by the method to be different than the type of the class that contains the method. In fact, the type returned can depend on the parameters. For example, EnumSet.of(E) will return a different type if the emum type has very few elements vs if the enum type has many elements (Edit: in this particular case, improving performance for the common case where the enum doesn't have many elements)
It allows caching. For instance, Integer.valueOf(x) will, by default, return the same object instance if called multiple times with the same value x, if x is between -128 and 127.
It allows you to have named constructors (which can be useful if your class needs many constructors). See, for example, the methods in java.util.concurrent.Executors.
It allows you to create an API that is conceptually simple but actually very powerful. For instance, the static methods in Collections hides many types. Instead of having a Collections class with many static methods, they could have created many public classes, but that would have been harder for someone new to the language to understand or remember.
For generic types, it can limit how much typing you need to do. For example, instead of typing List<String> strings = new ArrayList<String>() in Guava you can do List<String> strings = Lists.newArrayList() (the newArrayList method is a generic method, and the type of the generic type is inferred).
For HashBiMap, the last reason is the most likely.
This is usually done because the class actually instantiated by the create() method might be different than the type upon which you are invoking the method. i.e. a factory pattern where the create() method returns a specific subclass that is appropriate given the current context. (For example, returning one instance when the currrent environment is Windows, and another when it is Linux).
Unlike constructors, static methods can have method names. Here's a recent class I wrote where this was useful:
/**
* A number range that can be min-constrained, max-constrained,
* both-constrained or unconstrained.
*/
public class Range {
private final long min;
private final long max;
private final boolean hasMin;
private final boolean hasMax;
private Range(long min, long max, boolean hasMin, boolean hasMax) {
// ... (private constructor that just assigns attributes)
}
// Static factory methods
public static Range atLeast (long min) {
return new Range(min, 0, true, false);
}
public static Range atMost (long max) {
return new Range(0, max, false, true);
}
public static Range between (long min, long max) {
return new Range(min, max, true, true);
}
public static Range unconstrained () {
return new Range (0, 0, false, false);
}
}
You couldn't do this using just constructors, as atLeast and atMost would have the exact same signature (they both take one long).
This is called a Factory method pattern. Where the factory lies within the class itself. Wikipedia describes it pretty well but here are a few snippets.
Factory methods are common in toolkits and frameworks where library code needs to create objects of types which may be subclassed by applications using the framework.
Parallel class hierarchies often require objects from one hierarchy to be able to create appropriate objects from another.
Well it would be possible for SomeClass.create() to pull an instance from a cache. new SomeClass() won't do that without some shenanigans.
It would be also be possible for create() to return any number of implementations of SomeClass. Basically, a Factory type of dealio.
Although not applicable to this particular code example, the practice of hiding the constructor behind a static method is Singleton Pattern. This is used when you want to ensure that a single instance of the class is created and used throughout.
There are many reasons to use this factory method pattern, but one major reason Guava uses it is that it lets you avoid using type parameters twice when creating a new instance. Compare:
HashBiMap<Foo, Bar> bimap = new HashBiMap<Foo, Bar>();
HashBiMap<Foo, Bar> bimap = HashBiMap.create();
Guava also makes good use of the fact that factory methods can have useful names, unlike constructors. Consider ImmutableList.of, ImmutableList.copyOf, Lists.newArrayListWithExpectedSize, etc.
It also takes advantage of the fact that factory methods don't necessarily have to create a new object. For instance, ImmutableList.copyOf, when given an argument that is itself an ImmutableList, will just return that argument rather than doing any actual copying.
Finally, ImmutableList's factory methods return (non-public) subclasses of ImmutableList such as EmptyImmutableList, SingletonImmutableList and RegularImmutableList depending on the arguments.
None of these things are possible with constructors.
i got very interesting reason to hide constructor check it and please let me know if there is any other alternative to achieve this
enter code here
Class A
{
String val;
protected A( )
{
}
protected A(String val)
{
this.val=val;
}
protected void setVal( String val)
{
this.val=val;
}
public String getVal()
{
return val;
}
}
class B extends A
{
B()
{
super();
}
public val setVal(String val)
{
super.val=val;
}
}
class C extends A
{
C(String val)
{
super(val);
}
}
Some main reasons
Primarily it gives you the power to instantiate a different (sub) class
Possibility to return null
It enables you to return an already existing object