8
class Employee{

    String name;
    int id;

   //No explicit constructors
}

Now I can invoke the following statement:

Employee e1 = new Employee();

With the above code, the compiler will provide the definition for the constructor Employee().

If I define a single explicit constructor as follows:

 class Employee{

    String name;
    int id;

    Employee(String aName){
        this.name=aName;
    }
}

Now, why can't I invoke the following statement:

Employee e2 = new Employee();

Even though the compiler knows how to provide definition of Employee().

Now, just because I have defined an explicit constructor Employee(String aName), why can't I use a default constructor?

Also, if the compiler had allowed the use of the default constructor even after defining an explicit one, it would have helped us to reuse the code for default constructor.

  • 7
    It wouldn't be a default constructor anymore. I would be a constant constructor because it's always there. – Reactgular Oct 3 '14 at 17:05
6

First of all, default constructor is not generated, its provided by compiler if no-argument constructor is not written explicitly.

When you do not explicitly write a no-argument constructor for a class, the compiler won't complain as long as objects are built without parameter constructors.(since compiler allows default constructor to create objects, which itself gives call to no-argument constructor).

But if you do define a no-argument constructor, when compiling, compiler will check for the call to constructor and its definition in class. It's just like authenticating any other method of a class.

So it will give an error if you call no-argument constructor after defining a parameterised constructor, since it finds no no-argument constructor explicitly defined in class. And, this is logically correct since, if you want to block creation of objects without any data in it, this is one good way.

For example, consider that an employee object must have an employee id associated to it. For achieving this, define a single argument constructor and don't define no-argument constructor.

38

A constructor with arguments isn't just a handy shorthand for using setters. You write a constructor in order to ensure that an object will never, ever exist without certain data being present.

If there is no such requirement, fine. But if there is one, as indicated by the fact that you've written such a constructor, then it would be irresponsible to generate a default constructor, through which a client could circumvent the "no object without data" rule. Doubly so, because the auto-generated default constructor is invisible to a casual code reader, which hides the fact that it exists! No, if you want constructors with arguments and a default constructor, you must write the default constructor yourself. It's not as if it's a lot of effort to write an empty block, anyway.

  • 4
    well said, if I write a constructor with parameters, it's because those values are needed for the class instances to work. If I have some useful defaults, I'll write a no-args constructor calling the other constructor while supplying those defaults. – jwenting Oct 3 '14 at 8:14
  • +1. Additionally, if you couldn't guarantee that fields will be initialized in the constructor, you could never have immutable objects, which is what you should prefer. – Doval Oct 3 '14 at 11:22
  • 2
    @Doval: which you should prefer, in certain situations. Like everything else, immutable objects have trade-offs making them good for some situations and not for others. No silver bullet. – whatsisname Oct 3 '14 at 17:04
  • 1
    @whatsisname Never called it a silver bullet, but it's the better default. – Doval Oct 3 '14 at 17:19
  • This Answer is very helpful to read in conjunction with the also-good Answer by Konrad Morawski: His Answer provides a nice real-world analogy to explain essentially the same answer. – cellepo Oct 25 '18 at 19:48
8

Java generating a parameterless constructor when you don't have any other is like a polite waiter taking your coat for you.

Java still generating a parameterless constructor after you define another version of it is like the same waiter taking the coat off you after you gave a clear indication that you have your own plans of what to do with the coat.

If I have a class (that I want to be immutable):

class Person
{
    final String firstName;
    final String lastName;

And I add a constructor:

    Person(String firstName, String lastName) 
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

And Java was still to provide a default, parameterless constructor, then this code can't compile, because firstName and lastName fields are declared as final, yet they are not set after you call Person p = new Person().

You are forcing me to provide another implementation:

private Person() 
{
    this.firstName = null; // or "", or whatever
    this.lastName = null;
}

And since I don't want it - as it's useless, I might feel inclined to put skull and crossbones on it:

@Deprecated
private Person() 
{
    // don't use this constructor! i don't want it to ever be called!
    throw new RuntimeException("Illegal constructor called");
}

But I still can't forbid another developer to create a method (inside the Person class, so marking the constructor as private didn't help):

public static Person createPerson()
{
    return new Person(); // this will blow in our face
}

All this fuss could be - and is - avoided thanks to the fact that Java (and not only Java) works the way it works.

If you define a method setCoordinates(int x, int y), you don't expect compiler to automatically accept a parameterless version of it - setCoordinates(). It wouldn't do a thing.

How is this different from expecting a parameterless constructor? Well, obviously, a constructor always does at least one thing - it creates an object (or dies trying).

But I like to be in control of how I want my objects to be instantiated. Forcing me to have a parameterless constructor no matter what I do takes this control away from me.

  • This Answer is very helpful to read in conjunction with the also-good Answer by Kilian Foth. I love the creativeness of the waiter/coat explanation/analogy, which is valid and works! – cellepo Oct 25 '18 at 19:43
3

The language puts the default constructor in as a favor to you. The presumption is that if you've written a custom constructor, your no-argument constructor may well require special attention too. Not a great reason, but not horrible, either.

The secondary reason id that cruft just gets pile onto that language with no thought to its symmetry with existing practice and very little interest in making it readable. Stoustroup's original "C with Classes" was a hacked up C-preprocessor which probably shouldn't made it out of the lab. The world's funny that way.

3

If you define a constructor with a parameter, then there must be a valid reason in doing so. Maybe this parameter is so important to your class that without it the object state is invalid. That is why the Java does not make a no-argument constructor for you when you already define one.

If you decide that it would be handy to have no-arg constructor, then you can still define it:

Employee(){
  // good practice to call existing constructor with your favorite value
  this("");
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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