Related
I provide an API and need to know, where methods of the API were invoked. I could of cause use reflection or the thread stacktrace, but that would include a lot of runtime cost.
I do not need the exact class name, a unique reference per invocation would be sufficient. In C I would normally use the preprocessor to automatically add __FILE__ and __LINE__ to the method invocation.
Is there a method in Java (besides code generation) to get a unique caller identification with low runtime cost?
One solution would be to have a cached Throwable which is passed in.
class StackPoint {
Throwable stack;
public Throwable getStack() {
if (stack == null)
stack = new Throwable();
return stack;
}
}
public void methodToCall(StackPoint sp) {
Throwable t = sp.getStack();
}
static final StackPoint one = new StackPoint();
methodToCall(one); // Have to remember to give each line a different StackPoint.
Note: if the method which calls this caller changes, you only record the first one ever.
There isn't a standard pattern and it is likely that if you want this to be efficient the caller will need to pass a unique id. The closest you can do is use is a lambda.
public void methodToCall(Runnable run) {
Class id = run.getClass();
}
You can call it like this
methodtoCall(()->{});
This will create a different class for each place it is called, even if it appears multiple times on the same line. It creates no garbage as it reuses the same object each time. You could make this shorter with
void methodToCall(IntFunction fun) {
}
and call
methodToCall(a->1);
As something asynchroneous is involved, split the call up, and let the API return the ID.
Ticket callTicket = api.call(params);
Logger.getLogger(getClass().getName(), Level.FINE, callTicket);
Result result = callTicket.get();
Above having a result returned (synchroneously) is probably not the case with your code. Your code will get the result delived elsewhere. But that could be a ticket system too.
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 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.
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 really love how guava library allows simple one-liners for checking for null:
public void methodWithNullCheck(String couldBeNull) {
String definitelyNotNull = checkNotNull(couldBeNull);
//...
}
sadly, for simple argument check you need at least two lines of code:
public void methodWithArgCheck(String couldBeEmpty) {
checkArgument(!couldBeEmpty.isEmpty());
String definitelyNotEmpty = couldBeEmpty;
//...
}
however it is possible to add method which could do argument check and return a value if check successful. Below is an example of check and how it could be implemented:
public void methodWithEnhancedArgCheck(String couldBeEmpty) {
String definitelyNotEmpty = EnhancedPreconditions.checkArgument(couldBeEmpty, !couldBeEmpty.isEmpty());
//...
}
static class EnhancedPreconditions {
public static <T> T checkArgument(T reference, boolean expression) {
if (!expression) {
throw new IllegalArgumentException();
}
return reference;
}
}
I just was wondering is that by design and if it is worth to put feature request for that.
EDIT: #Nizet, yeah, checks in methods could be clumsy. However checks in constructors for nulls looks really good and saves a lot of time spent on debugging NPEs:
public class SomeClassWithDependency {
private final SomeDependency someDependency;
public SomeClassWithDependency(SomeDependency someDependency) {
this.someDependency = checkNotNull(someDependency);
}
//...
EDIT: Accepting Nizet's answer because I agree with him on side-effects and consistency reasoning.
Also if you take a look into Xaerxess comment it looks like that causing confusion amongst other developers as well.
The biggest single reason that checkNotNull returns its argument is so it can be used in constructors, like so:
public Foo(Bar bar) {
this.bar = checkNotNull(bar);
}
But the main reason that checkArgument doesn't do something similar is that you'd have to pass the argument separately anyway, and it just doesn't seem worth it -- especially with more complicated precondition checks, which can sometimes be more readable on their own line. Just because something can be a one-liner doesn't mean that it should be, if it doesn't increase readability.
What I've never understood is why checkNotNull() returns its argument in the first place:
public void foo(String bar) {
Preconditions.checkNotNull(bar);
// here, you're sure that bar is not null.
// No need to use another variable or to reassign bar to the result
// of checkNotNull()
}
I personally ignore the result of checkNotNull(), as above. And this makes things consistent with the other checks which return void.
The only advantage I see is that you can do something like that, but I find it less readable than doing it in two separate lines:
public String trim(String bar) {
return Preconditions.checkNotNull(bar).trim();
}
So, in short, I agree with you that the API is somewhat inconsistent, but I would prefer for all the methods to return void. A method should either have a side effect, or return something, but doing both should be avoided generally. Here, the goal of the method is to have a side effect: throwing an exception.
EDIT:
Your example is indeed a more valid explanation of why returning the argument is useful. But I would still have favored consistency and cleanness instead of this possibility of checking and assigning in a single line.
You can use valid4j with hamcrest-matchers instead (found on Maven Central as org.valid4j:valid4j)
For preconditions and postconditions:
import static org.valid4j.Assertive.*;
this.myField = require(argument, notNullValue());
this.myInteger = require(x, greaterThan(0));
...
return ensure(result, isValid());
For input validation:
import static org.valid4j.Validation.*;
validate(argument, isValid(), otherwiseThrowing(InvalidException.class));
Links:
http://www.valid4j.org/
https://github.com/helsing/valid4j