2

I am struggling to fully understand the usage of constructors in Java.

What I have learned so far about constructors is the following:

  • same name as class
  • abbreviation ctor
  • overloading
  • no return type
  • create an object of a class
  • every class has a default constructor

When for example a string has to be returned from a class that needs to be called then a method could be created, i.e. a constructor will not be sufficient as this will not return anything.

Attempt to answer the question

In order to explain what I mean, I have created a class with two constructors and two methods that return a string.

public class HelloWorldConstructor {
    public HelloWorldConstructor() { }

    public HelloWorldConstructor(String a) {
        saySomething(a);
    }

    public HelloWorldConstructor(String a, String b) {
        saySomething(a, b);
    }

    void saySomething(String a) {
        System.out.println(a);
    }

    void saySomething(String a, String b) {
        System.out.println(a + ", " + b);
    }
}

Option 1

It is possible to return a string by calling the method that resides in the class.

public class CallConstructor {
    public static void main(String[] args) {
        HelloWorldConstructor hwc = new HelloWorldConstructor();

        hwc.saySomething("allo");
        hwc.saySomething("allo", "allo");
    }
}

returns:

allo
allo, allo

Option 2

It is also possible to return a string by calling the constructor directly.

public class CallConstructor2 {
    public static void main(String[] args) {
        new HelloWorldConstructor("allo");
        new HelloWorldConstructor("allo", "allo");
    }
}

returns the same as option 1.

Discussion

When option 2 is chosen, then two objects have to be created instead of one as depicted by option 1, but when to choose option 2 and when option 1? In this case I think it is better to choose option 1 as one object will be created, but option 2 could be suitable when other circumstances are applicable.

Using Constructors in Java

The constructor in the example just gives an initial value to class members.

https://stackoverflow.com/a/19941847/2777965

Constructors are used to initialize the instances of your classes. You use a constructor to create new objects often with parameters specifying the initial state or other important information about the object

After reading about theory and Q&As about constructors I am struggling to fully understand them. I know how to call a constructor and how to call a method, but I cannot rationalize this.

  • A constructor has to be called directly when ...
  • Constructor overloading will be done when ...
  • Methods will be called directly by calling the default constructor when ...
7
  • Do you understand that in the first example you are creating one string object but you are creating three in the second example? Commented Jan 1, 2018 at 22:55
  • You are right. I will update the sample.
    – 030
    Commented Jan 1, 2018 at 22:55
  • 9
    Your example does not return anything, it outputs ie. displays the strings. Commented Jan 1, 2018 at 23:37
  • 1
    And now options 1 and 2 don't output anything at all or use what was returned. Also you've invalidated the answers. Commented Jan 2, 2018 at 20:04
  • 2
    I think the reason you are having a tough time with these concepts is that your sample learning code is too simplistic. Why churn up a class to write something to the screen, instead of just writing to the screen? Make something real, like say a cash register. You start off with a certain amount. So the constructor gets passed that amount. Then you have methods to do various operations, like add or deduct as items are sold. It will become clear what the difference is between ctor and methods. Then, expand your store and add another register by reusing your code. Commented Jan 2, 2018 at 20:11

4 Answers 4

6

You call a constructor when you want to create a new object instance. For example if you have a class Button, then you call the constructor if you want to create a new Button instance.

If you don't need a new object, then don't use a constructor. In your example you just use the constructor as a convoluted way of calling a method, but you don't actually use the created object (the result of the new-expression) for anything. This is a clear hint that you don't need to call a constructor. If you made saySomething static you would not need to call any constructors.

The reason for your confusion is probably that the HelloWorldConstructor class does not really have any purpose beyond writing output. Therefore it is not obvious whether you should have one or two instances of it. In reality you don't need any instance at all.

7
  • 2
    +1 The simple answer here is use constructors to create objects. Use methods for everything else.
    – JimmyJames
    Commented Jan 2, 2018 at 19:09
  • Using static methods simply to avoid the need to call a constructor is a micro optimization that sticks it's thumb in the eye of polymorphism. But other than that I like this answer very much. Commented Jan 2, 2018 at 20:00
  • @CandiedOrange I don't see the answer as saying you should use static to avoid calling a constructor. It doesn't make a lot of sense to me to create an object just to call a method.
    – JimmyJames
    Commented Jan 2, 2018 at 21:22
  • @JimmyJames The only reason to create an object is so you can call a method. The reason to prefer the object over a static reference is because you don't have to know exactly which method implementation you're calling. Stick behavior in a static method and I'm stuck knowing exactly what I'm talking to. I'd rather not know. Commented Jan 2, 2018 at 21:46
  • @CandiedOrange You create objects if you want to have behavior related to the state of that object. If you have no state, the object is just a pointless allocation on the heap (assuming it's not optimized away, which it probably will be). Better to just do the simplest thing and refactor later if and when you need it.
    – JimmyJames
    Commented Jan 2, 2018 at 22:14
4

same name as class

True, in java

abbreviation ctor

True

overloading

True

no return type

Well... no explicit return. A ctor always has an implicit return type. The class is the type. A ctor, when used with the new keyword, returns the object it creates and that object's type is the class. Thankfully, when you define a ctor you don't have to say the class name yet again.

create an object of a class

That is what it does.

every class has a default constructor

Well... no. As wikipedia puts it:

In both Java and C#, a "default constructor" refers to a nullary constructor that is automatically generated by the compiler if no constructors have been defined for the class. The default constructor implicitly calls the superclass's nullary constructor, then executes an empty body.

Wikipedia: Default Constructor

So no, not every class has a default constructor. Every class will have some constructor. It only has the default constructor if you don't define one for it explicitly.

BTW, "nullary constructor" is a fancy way to say a no argument constructor.

When for example a string has to be returned from a class that needs to be called then a method could be created, i.e. a constructor will not be sufficient as this will not return anything.

Ugg. Look, there are constructors that "return" strings just fine. They all live in the String class.

In order to explain what I mean, I have created a class with two constructors and two methods that return a string.

No you haven't. Outputting is not returning. Your constructors don't return strings. They "return" objects of the HelloWorldConstructor type.

Which is why this compiles:

HelloWorldConstructor hwc = new HelloWorldConstructor();

Option 1: it is possible to return a string by calling the method that resides in the class.

It would be if your methods returned strings. They return void. Again, outputting is not returning.

Option 2: It is also possible to return a string by calling the constructor directly.

You mean output a string. Yes you can make a constructor do other things besides simply construct the object, as God intended. That doesn't mean it's a good idea.

When option 2 is chosen, then two objects have to be created instead of one as depicted by option 1, but when to choose option 2 and when option 1? In this case I think it is better to choose option 1 as one object will be created, but option 2 could be suitable when other circumstances are applicable.

Construction of objects and use of objects should happen in seperate places. Mashing them together like this just makes a mess.

A constructor has to be called directly when ...

When you're constructing the object. Put it in a handy variable and pass it to something that would use it.

Constructor overloading will be done when ...

... you can't make up your mind what your object should depend on. If you can think of many ways to build the same object then you write many constructors that build it those many ways.

Methods will be called directly by calling the default constructor when ...

Sorry this just makes no sense. You call methods on objects when it's time to use them. You call constructors (default or not) when it's time to build them.

Again, you do not have to build and use at the same time. In fact it's usually better if you don't. Polymorphism only works when you don't know exactly what you're talking to.

When to call the constructor and when to call the method in Java?

Best answer I have for this comes from Dependency Injection which says to do your construction as high up the call stack as you can. Which pretty much means do construction in main. Personally I don't mind if you use some Creational Patterns that take you out of main for a bit but keep the behavior code away from there.

8
  • 1
    You said everything I wanted to and I agree with everything except that there is no God :) Commented Jan 2, 2018 at 14:13
  • 2
    Re A ctor always has an implicit return type. Not really. What a constructor returns (if anything) is an implementation detail. This is very much the case in C++, which motivated Java. This is not so much the case in Java, where the implementation detail is the JVM. In Java, it is the new operator (not the ctor) that allocates the memory, and it is the new operator (not the ctor) that returns the constructed reference to the caller. There is no need for a ctor to return anything, which is exactly how constructors are implemented in the JVM (they return void). Commented Jan 2, 2018 at 15:50
  • @DavidHammen better? Commented Jan 2, 2018 at 16:47
  • 1
    @AluanHaddad - you seem to be trying to imply that Brian Goetz doesn't exist, but I swear I've seen Him posting here from time to time...
    – Jules
    Commented Jan 3, 2018 at 5:47
  • 1
    @DavidHammen I disagree. That is the implementation detail. Conceptually, a constructor is very much like a function which returns an object. The syntactic distinction between constructors and factories in C++ derived syntax doesn't change this and it isn't universal. For example in Scala a case class is callable (I know that's not what really happens, that it's actually a call to a callable synthesized factory object, but that's the whole point) If you declare case class you can use it as a function and it will construct an object. Commented Jan 3, 2018 at 9:44
3

Our job as programmers is to offer automation to various real-world domains — doing that often requires us to represent various domain concepts, their relationships, and their behaviors or capabilities.

In programming, we represent various concepts, relationships, and behaviors using the programming language's capabilities for defining abstractions. Abstractions, because while on the one hand they model some domain concepts, relationships, and behaviors, yet on the other hand, they have internal implementation details (e.g. state & algorithms) that we prefer to shield from the consuming client programmer (often ourselves) to reduce complexity and ease programmer burdens.

The class is one mechanism for creating abstraction. It allows bundling of methods and state in a single entity that can be manipulated by a consuming client programmer.

Importantly, the class construct allows for customizable instances. Instance customization is usually done through parameters passed to the constructors. Constructors offer the capabilities to bind an instance to certain values or certain other objects.

Once constructed, an instance can now be used to access behaviors and relationships of the concept, by using its methods.

Typical of using abstractions, we separate concerns, and create objects in one place and use them in others: object creation represents a milestone of some sorts, and once created, an instance can be handed off to be used by some other consuming client programmer, capable of working with different object instances of the same type (class or interface) regardless of how they were created.


Your class HelloWorldConstructor, is obviously an just an arbitrary sample for purposes of your question — we wouldn't usually name a class after the ability to construct, but after the abstraction that its instances represent.

This class is also overly simplistic in that it doesn't have any state. (While it is sometimes reasonable to have an instance without state, useful scenarios of that usually involve multiple different classes that are sharing some interface (or base class).) Without state, the constructor is not binding anything — to put it another way, the constructor is not participating in creating a customized instance.

Still, all that being said, your option 1 is more in the style of object oriented programming than the other because it creates an instance and later uses it — even though it does this in immediately adjacent lines of code.

Your option 2 is effectively a procedural form of programming (i.e. not OOP) since you're doing all the work in the constructor and then throwing away the instance that's been created.


A typical scenario is to use the constructor to customize an instance, and then, once created, hand the customized instance off to some more generic code that can work with any instance of that class. That more generic code then carries out some useful behaviors with the customized instance.

For example, add a parameter to the constructor to take a name as a string. Now the contructor's job is merely to capture that name.

public class SayHi {
    private String name;

    public SayHi(String toWhom) {
        name = toWhom;  // capture customization parameter
    }

    public void saySomething(String a) {
        System.out.println(name + ": " + a);
    }
}

We can now create differently customized instances new SayHi("Erik") ... new SayHi("030"), and use those different instances with the same code.

-5
  • A constructor has to be called directly when ...

Never.

You invoke a constructor by using the new key word and the JVM will invoke the constructor for you.

  • Constructor overloading will be done when ...

You write brittle code.

Constructor overloading means that you have more than one constructor in the same class.

Constructors should set (final) instance variables (aka members or fields) of the object (and nothing else except simple validations). Since different constructors must have different parameter types or different parameter count the consequence of having them is one of four cases:

  1. You only set the the members having relates parameters passed in into the individual ctor.

    The result of this is that you have to assign null to members not relating to a parameter of the current ctor. This usually means that you have an invalid object forcing you to throw null-checks throughout your code.

  2. You assign some default values to members not relating to a parameter of the current ctor or call another ctor in this class passing the current parameters and those default values. (constructor chaining)

    The consequence of this is that you hide the real dependencies of your class from the user. Users of your class may be confused.

  3. You "calculate" the missing values.

    Ctors should not do any calculation, just initializing the members. Anything else will make your class hard to reuse.

  4. You acquire missing values by accessing static methods in other classes (singeltons by any chance...)

    This is the worst case since it creates an unbreakable hidden coupling to this other (singeton) class.

As a rule of thumb: A class should have one ctor only.

  • Methods will be called directly by calling the default constructor when ...

Never.

A constructor (as already written) only assigns values to members. It does not calculate anything and therefore it should not call any other method within the class.


As you become experienced you might find valid reasons to brake these rules, but as a beginner you should stick to them.

5
  • 2
    -1 for "ctors should not do any calculation, just initializing the members," amongst others. Constructors oftentimes calculate things in order to initialize the members. The route this answer advocates is the route of getters and setters for every data member. Might as well make them all public, in that case. Commented Jan 2, 2018 at 0:55
  • 3
    -1 for the comment on constructor overloading. Many Java library classes have overloaded constructors. Commented Jan 2, 2018 at 1:44
  • @DavidHammen "The route this answer advocates is the route of getters and setters for every data member." No. The route this answer advocates is to calculate these values before passing them to the ctor. Commented Jan 2, 2018 at 11:07
  • @kevincline "Many Java library classes have overloaded constructors." As I wrote experienced programmers may find valid reasons to provide overloaded ctors. But this post is to an obvious novice. Commented Jan 2, 2018 at 11:10
  • @TimothyTruckle - if the calculation details are private to the implementation of the class, then clearly performing them before passing to the constructor will be a bit tricky (although, that said, I'm generally a fan of using a static method that returns an object for most non-trivial initialisation....)
    – Jules
    Commented Jan 3, 2018 at 5:50

Not the answer you're looking for? Browse other questions tagged or ask your own question.