Can I call methods in constructor in Java?
Better design would be
public static YourObject getMyObject(File configFile){
//process and create an object configure it and return it
}
- Factory design pattern
Calling method from constructor
Is this expected Java behavior?
Yes.
What could cause this?
Your invocation of non-final overridden method in non-final super class constructor.
Let's see what happens step-by-step:
- You create an instance of
B
. B()
calls super class constructor -A()
, to initialize the super class members.A()
now invokes a non-final method which is overridden inB
class, as a part of initialization.- Since the instance in the context is of
B
class, the methodload()
invoked is ofB
class. load()
initializes theB
class instance field -testString
.- The super class constructor finishes job, and returns (Assuming chaining of constructor till
Object
class have been finished) - The
B()
constructor starts executing further, initializing it's own member. - Now, as a part of initilization process,
B
overwrites the previous written value intestString
, and re-initializes it tonull
.
Moral: Never call a non-final public method of a non-final class in it's constructor.
Calling methods from the constructor
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.
Why is it considered bad practice in Java to call a method from within a constructor?
First, in general there's no problem with calling methods in a constructor. The issues are specifically with the particular cases of calling overridable methods of the constructor's class, and of passing the object's this
reference to methods (including constructors) of other objects.
The reasons for avoiding overridable methods and "leaking this
" can be complicated, but they basically are all concerned with preventing use of incompletely initialised objects.
Avoid calling overridable methods
The reasons for avoiding calling overridable methods in constructors are a consequence of the instance creation process defined in §12.5 of the Java Language Specification (JLS).
Among other things, the process of §12.5 ensures that when instantiating a derived class[1], the initialisation of its base class (i.e. setting its members to their initial values and execution of its constructor) occurs before its own initialisation. This is intended to allow consistent initialisation of classes, through two key principles:
- The initialisation of each class can focus on initialising only the members it explicitly declares itself, safe in the knowledge that all other members inherited from the base class have already been initialised.
- The initialisation of each class can safely use members of its base class as inputs to the initialisation of its own members, as it is guaranteed they've been properly initialised by the time the initialisation of the class occurs.
There is, however, a catch: Java allows dynamic dispatch in constructors[2]. This means that if a base class constructor executing as part of the instantiation of a derived class calls a method that exists in the derived class, it is called in the context of that derived class.
The direct consequence of all of this is that when instantiating a derived class, the base class constructor is called before the derived class is initialised. If that constructor makes a call to a method that is overridden by the derived class, it is the derived class method (not the base class method) that is called, even though the derived class has not yet been initialised. Evidently this is a problem if that method uses any members of the derived class, since they haven't been initialised yet.
Clearly, the issue is a result of the base class constructor calling methods that can be overriden by the derived class. To prevent the issue, constructors should only call methods of their own class that are final, static or private, as these methods cannot be overridden by derived classes. Constructors of final classes may call any of their methods, as (by definition) they cannot be derived from.
Example 12.5-2 of the JLS is a good demonstration of this issue:
class Super {
Super() { printThree(); }
void printThree() { System.out.println("three"); }
}
class Test extends Super {
int three = (int)Math.PI; // That is, 3
void printThree() { System.out.println(three); }
public static void main(String[] args) {
Test t = new Test();
t.printThree();
}
}
This program prints 0
then 3
. The sequence of events in this example is as follows:
new Test()
is called in themain()
method.- Since
Test
has no explicit constructor, the default constructor of its superclass (namelySuper()
) is called. - The
Super()
constructor callsprintThree()
. This is dispatched to the overriden version of the method in theTest
class. - The
printThree()
method of theTest
class prints the current value of thethree
member variable, which is the default value0
(since theTest
instance hasn't been initialised yet). - The
printThree()
method andSuper()
constructor each exit, and theTest
instance is initialised (at which pointthree
is then set to3
). - The
main()
method callsprintThree()
again, which this time prints the expected value of3
(since theTest
instance has now been initialised).
As described above, §12.5 states that (2) must happen before (5), to ensure that Super
is initialised before Test
is. However, dynamic dispatch means that the method call in (3) is run in the context of the uninitialised Test
class, leading to the unexpected behaviour.
Avoid leaking this
The restriction against passing this
from a constructor to another object is a little easier to explain.
Basically, an object cannot be considered fully initialised until its constructor has completed execution (since its purpose is to complete the initialisation of the object). So, if the constructor passes the object's this
to another object, that other object then has a reference to the object even though it hasn't been fully initialised (since its constructor is still running). If the other object then attempts to access an uninitialised member or call a method of the original object that relies on it being fully initialised, unexpected behaviour is likely to result.
For an example of how this can result in unexpected behaviour, please refer to this article.
[1] Technically, every class in Java except
Object
is a derived class - I just use the terms 'derived class' and 'base class' here to outline the relationship between the particular classes in question.[2] There's no reason given in the JLS (as far as I'm aware) as to why this is the case. The alternative - disallowing dynamic dispatch in constructors - would make the whole issue moot, which is probably exactly why C++ doesn't allow it.
Calling methods inside Constructor
The reason the child method is called is because virtual method dispatch is the norm in Java. When you call the method, it decides which method to actually call at runtime based on the actual type of the object.
As for why it prints 0, that's because i
hasn't been set to 45 yet. Each field is initialized with a default value for that type, 0
in the case of integers. When you write int i = 45
, the compiler will generate code in the constructor to set i = 45
. But it places this code after the parent constructor is called. Therefore, you're printing the variable before it is initialized with its intended value.
Is it possible to call function from a constructor in java
You're not designing this in a good way :
- name with UpperCaser for
classes
and lowerCaser for attributs/variables - use different constructors, one for real
Rectangle
and one forRectangle
that aresquare
class Rectangle{
private int width;
private int height;
public Rectangle(int a, int b){
this.width=a; this.height=b
}
public Rectangle(int c){
this(c, c);
}
public int getArea(){
return width*height;
}
}
class session1{
// two ways of using it
public static void main(String args[]){
System.out.println("The area of rectangle is: "+new Rectangle(20,10).getArea();
Rectangle obj = new Rectangle(10);
System.out.println("The area of square is: "+obj.getArea());
}
}
Call a method after the constructor has ended
You either have to do this on the client side, as so:
A a = new A();
a.init();
or you would have to do it in the end of the constructor:
class A {
public A() {
// ...
init();
}
public final void init() {
// ...
}
}
The second way is not recommended however, unless you make the method private or final.
Another alternative may be to use a factory method:
class A {
private A() { // private to make sure one has to go through factory method
// ...
}
public final void init() {
// ...
}
public static A create() {
A a = new A();
a.init();
return a;
}
}
Related questions:
- What's wrong with overridable method calls in constructors?
- Java call base method from base constructor
Call static method from constructor in Java
Even though it's possible to do so, do not call methods from constructors.
Well, as I already said in the comments, it's perfectly fine to call methods from constructors. Either the author doesn't really understand it all, or this sentence is poorly-worded.
Calling overridable methods of the instance you're currently constructing will cause problems, as it'll leak half-constructed objects. See here for more info. But it looks like you're already aware of this.
Also, if you pass
this
to another method from within a constructor, then you're passing the half-constructed instance. Bad. Don't do it.
But for all other cases, calling another method will cause no problem at all. When you call a method, it is executed, and when it returns, control is passed back to the constructor, which happily continues with constructing the object.
There is absolutely no problem with your code:
TestClass(int number) {
if (NumberUtils.isGreaterThanOne(number)) {
this.number = number;
} else {
throw new IllegalArgumentException("Number must be above 1");
}
}
If it were bad to call other methods from the constructor, you had to implement the check employed by isGreaterThanOne
all here in the constructor itself. But instead, you happily delegate this to a separate method, which can be separately tested. So you're actually validating the input, which should be done.
Another way to write the validation, is to write guard clauses:
TestClass(int number) {
// This check here immediately throws an exception if number has an
// invalid value. This is called a a guard clause, and are usually
// positioned at the top of the method or constructor.
if (!NumberUtils.isGreaterThanOne(number)) {
throw new IllegalArgumentException("Number must be above 1");
}
// Continue with normal operation
}
But this is just another way of writing the same logic.
How do I call one constructor from another in Java?
Yes, it is possible:
public class Foo {
private int x;
public Foo() {
this(1);
}
public Foo(int x) {
this.x = x;
}
}
To chain to a particular superclass constructor instead of one in the same class, use super
instead of this
. Note that you can only chain to one constructor, and it has to be the first statement in your constructor body.
See also this related question, which is about C# but where the same principles apply.
How to call a method from a class given that I have the Constructor for it?
I was able to do it like this:
Constructor<?> productConstructor;
Class<?> productClass;
productConstructor = getProductConstructor(instance.getProductName());
productClass = getProductClass(instance.getProductName());
productClass.getMethod("run").invoke(productConstructor.newInstance(new Object[] { instance }));
public Constructor<?> getProductConstructor(String productName) {
try {
String fullQualifiedClassPath = "com.products." + productName;
logger.info("Looking for Product Constructor: {}", fullQualifiedClassPath);
Class<?> clazz = Class.forName(fullQualifiedClassPath);
return clazz.getConstructor(Instances.class);
} catch (Exception e) {
logger.error("Product: {} does not exist", productName);
}
return null;
}
public Class<?> getProductClass(String productName) {
try {
String fullQualifiedClassPath = "com.products." + productName;
logger.info("Looking for Product Class: {}", fullQualifiedClassPath);
return Class.forName(fullQualifiedClassPath);
} catch (Exception e) {
logger.error("Product: {} does not exist", productName);
}
return null;
}
Related Topics
Multiple Axes on the Same Data
Why Is Each Public Class in a Separate File
What's the Use of Session.Flush() in Hibernate
Java - Read File and Split into Multiple Files
Java Hashmap Performance Optimization/Alternative
How to Ensure in Java That the Current Local Time Is Correct
Compile Time VS Run Time Dependency - Java
Why Never Change the Notifier in Receiving a Change Event
Get Integer Value of the Current Year in Java
Difference Between Using Throwable and Exception in a Try Catch
Java/Jdk for the Apple M1 Chip
How Java Do the String Concatenation Using "+"
What Is the Best Open-Source Java Charting Library? (Other Than Jfreechart)
Java.Net.Connectexception :Connection Timed Out: Connect
Why Does Java's Java.Time.Format.Datetimeformatter#Format(Localdatetime) Add a Year