The Java compiler generates constructors and injects super constructor calls in many circumstances.
For example,
class Foo {
Foo() {}
}
becomes
class Foo {
Foo() {
super();
}
}
I am not keen on the different circumstances and I would like to make the code explicit.
How do you disable the Java compiler from doing this if it is possible?
You cannot disable the Java compiler from making calls to super - this is one of the core principles how object orientation was designed in Java.
You might however be able to tell your IDE to always display these calls (or not).
However I recommend to stick with the standard - every Java developer knows about it and what might look a bit odd and unfamiliar to you now will become perfectly reasonable after a short time... :)
Default constructor. If you don't define a constructor for a class, a default parameterless constructor is automatically created by the compiler. The default constructor calls the default parent constructor (super()) and initializes all instance variables to default value (zero for numeric types, null for object references, and false for booleans).
Default constructor is created only if there are no constructors. If you define any constructor for your class, no default constructor is automatically created.
The first statement in any subclass constructor is ALWAYS super(). There is no need to make a call to it because it will be supplied automatically if the superclass have a default constructor without params.
If the parent class doesn't have a default constructor, you have to add an super(params) call.
Remember all classes implicitly will extend Object if they do not extend any class explicitly
Related
Default constructors are provided by the compiler when the programmer fails to write any constructor to a class. And it is said that these constucors are used to initialize default values to the class attributes.However if the programmer provides a constructor, be it simple one like:
public class Main {
int a;
Main() { // user defined simple constructor
System.out.println("hello");
}
public static main(String[] args) {
Main obj = new Main();
}
}
In the above code the user has included a constructor. However it doesnot initialize the instance variable(a). Moreover default constructor won't be called. Then how come the variable 'a' gets initialized to it's default value.
If it is like, the default constructors do not initialize the class variables to their default values and compiler does it automatically, then what is the actual use of default constructor?
Why does the compiler add a default constructor in the case when the user fails to write a constructor?
Then how come the variable 'a' gets initialized to it's default value.
Because the language specifies that fields are initialized to their default values. Specifically, JLS 4.12.5:
Every variable in a program must have a value before its value is used:
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10.2):
...
For type int, the default value is zero, that is, 0.
...
Even if you did initialize it in the constructor, you could read the field beforehand, and observe its default value. For example:
Main() { // user defined simple constructor
System.out.println(a); // Prints 0
a = 1;
}
Although it is mostly hidden from you in Java, new Main() does two separate things (see JLS 15.9.4 for more detail, as it's actually more than two things):
It creates an instance of Main
Then it invokes the constructor in order to initialize that instance.
The initialization of the fields to their default values actually occurs when the instance is created (the first step, as described in the quote from JLS above); so, even if the second step of invoking a constructor didn't happen, the fields are still initialized to their default values.
Why does the compiler add a default constructor in the case when the user fails to write a constructor?
Because otherwise you wouldn't be able to create an instance of that class.
Additionally, the default constructor (like all constructors which don't call this(...) on their first line) invokes the super constructor. So, it would look something like:
Main() {
super();
}
You have to call the super constructor of a class in order to do the necessary initialization of the base class.
Default values
And it is said that these constucors are used to initialize default values to the class attributes.
That is incorrect. The constructors (including the default no-arg constructor) does not initialize the fields to their default values. This is done implicitly beforehand by the language already (see the JLS definition).
The default constructor is identical to a completely empty constructor:
Foo() {}
Technically, like other constructors, this implicitly still contains the call to the parent class constructor:
Foo() {
super();
}
Also have a look at the bytecode of public class Foo {}, which is:
public class Foo {
public Foo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
}
You can clearly see the default constructor with code to invoke Objects constructor.
Why add it in bytecode?
Why does the compiler add a default constructor in the case when the user fails to write a constructor?
In theory it would not have to do that. However, language-design wise it is much easier to just add it to simplify the rest of the language.
For example, then you do not need any magic to make new Foo(); work, since the constructor just actually exists in the code that the JVM executes.
Same holds for more advanced topics such as the reflection API, which has methods like
Object foo = Foo.class.getConstructor().newInstance();
So if the constructor just actually exists in the bytecode, again, you do not need any magic in the JVM to make this work. It just works out of the box.
At the end of the day it was a design decision by the developers to create it in the way they did. They could have realized it differently as well.
That way however, you have a much clearer split between Java and JVM bytecode as languages. And technically you can also create classes in bytecode that do not even have constructors at all (which you can not create from within Java), which is interesting to special tools and other languages that compile to JVM bytecode (Kotlin, Groovy, Scala, Clojure, ...).
Fields are initialised with defaut values (0, 0.0, null, false, etc...)
Default behavior is useful. The alternative may be deleting it if it isn't being used or putting it in another class, or setting it as null. Most of the time though, you do want default behavior. And that is the general idea, I believe.
In other words,
If a superclass does not have a default constructor, any subclasses extending it must make an explicit call to one of the superclass' parameterized constructors. why so?
It would be nice if you could try explaining it using Java.
Assume that your superclass has a field something and a constructor which initializes that field based on a passed parameter. You cannot create a child instance without properly initializing the super class. And if there is no default constructor the compiler cannot implicitly make the call. Instead it now it needs a parameter value to pass and the compiler cannot figure that value out on its own, instead you as the programmer need to explicitly state which parameter to pass to what super constructor.
This question already has answers here:
Why call super() in a constructor?
(8 answers)
Closed 5 years ago.
I'm a Java beginner learning about Java compiler rules as below:
If the class has no super class, extend it to Object class
If the class has no constructor, add a default no-parameter constructor
If the first line of the constructor is not "super()" or "this()", add "super()" to call the default constructor of the super class.
I understand that all objects we create are derived from the super class Object.
My question is what does the constructor in the Object class do when called?
Edit: My question is about what the constructor does in the class Object? I'm aware that subclasses call superclass's constructor by default.
For example, I have the following code (where I explicitly extend to Object and call super() to illustrate what the compiler does). My question is, what does the call to super() do?
public class Person extends Object
{
private String name;
public Person(String n)
{
super();
this.name = n;
}
}
My question is, what does the call to super() do?
It calls the default constructor for java.lang.Object. And to answer what you seem to be really asking, from the Java Language Specification, #8.8.9
8.8.9. Default Constructor
If a class contains no constructor declarations, then a default constructor is implicitly declared. The form of the default constructor for a top level class, member class, or local class is as follows:
The default constructor has the same accessibility as the class (§6.6).
The default constructor has no formal parameters, except in a non-private inner member class, where the default constructor implicitly declares one formal parameter representing the immediately enclosing instance of the class (§8.8.1, §15.9.2, §15.9.3).
The default constructor has no throws clauses.
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
Note the final paragraph.
All Java classes that don't have any explicit superclass, extend from Object, except for Object itself. There's no need to make it explicit in your code, the compiler will take care of.
Also, the super() call in the constructor will invoke the constructor of Object. If you look at the implementation, you'll see that Object doesn't have any constructor at all, so it'll use an implicit empty constructor which does nothing. Details such as constructing a vtable to make sure that the inherited methods are there to use or initialising the object's monitor are not part of the constructor but are performed by the JVM implementation when the new operator is called.
public Object() {
}
The Object class has few methods that come handy in most of the classes. For example, the infamous toString() is implemented in the Object class. Also, the hashCode() is implemented there.
I'd recommend you to have a deep look at the Object.class file to understand what methods are inherited in every single Java class.
Regarding your 3 rules at the top, are "good" for academic purposes but never used in reality. You'll never see an explicit extends Object, and only call the super() or this() when you need to overwrite the default behaviour.
Also, avoid abusing of inheritance and use more composition (implement an interface), although, it depends on the every use case.
For example, I have the following code (where I explicitly extend to
Object and call super()). My question is, what does the call do
super() do?
Actually, Object() does nothing.
Now you should not reduce the constraint to invoke super() (with args or not) for any subclass constructor to the case where you have a class that doesn't extend a class explicitly.
This case is the only one where invoking super() may seem not really useful.
But as soon a class extends a class distinct from Object, this constraint makes really sense as the child construction has to apply first its parent construction.
But the language specifies this point in a general way. It has no exception for classes that extend directly Object.
Probably because, it makes things more simple and that is not a real constraint as the compiler adds for you the call to the super default constructor : super().
Suppose I have one POJO class User with a constuctor public User(int id, String name){...}.
But when I instantiate the User object like User u=new User() with no parameter Eclipse gives error like The constructor User() is undefined. But it works fine when I have no parameterized Constructor. Can someone please explain why It requires to define default constructor?
The default (no-parameter) constructor is ONLY provided if you have provided no others. If you define even a single constructor for your class, you MUST use one of the explicitly defined (ie, in your code) constructors to instantiate the object. You can, of course, define your own zero-parameter, empty constructor if that works for what you're trying to do.
Edit:
Answer of why?
The compiler provides a default constructor so that the Object can be Instantiated when there are no constructors defined. But if you have defined a parametric constructor, it means that when you create a new instance of that class, its variables should initialized with the parameters you have passed(or do something similar). Without those initializations, the object might not behave in an expected way. Hence the compiler prevents such things from happening by not defining a default constructor(when you have defined one).
The no-arg constructor will be automatically added by the compiler if no constructor is provided by the developer. However, as soon as you put your own custom parameterized constructor, the compiler stops adding default constructor for you.
In this scenario, if you still want to use your no-arg constructor, you have to provide it yourself explicitly:
public User() {
}
public User(int id, String name) {
}
The logic behind this is that: if you define your own parametrized constructor, you are declaring that the parameters listed in the constructor is required to construct an object of the class. Therefore you are also implicitly declares if the user of your library do not provide these two parameters, the object shouldn't be able to construct. Thus the compiler will not add the no-arg constructor for you.
If you want to also declare that your class can still work if none of the specified parameters in the parametrized constructor is provided and you (no arg), then you have the explicitly declare that by providing the non-arg constructor yourself.
I am giving answer so late, but let's try to share with you what i know:
When you don't provide constructor compiler provides constructor. Why ? Because it is sure you are going to initialize your object with no argument constructor only. So compiler does it for you.
When you provide parameterised constructor, then compiler doesn't know which constructor you will use to initialize your object. So compiler does not provide for you one no-argument constructor. So you have to write explicitly.
Hope it will help you.
The compiler automatically provides a no-argument, default constructor for any class without constructors but if you explicitly provide any constructor with arguments then compiler will not provide a default constructor mainly due to security reasons.
So what you can do is
public User(int id, String name){...}
public User(){this(defualtID,defaultName)};
Java compiler automatically provides a no-parameter, default constructor for any class without constructors. If there is no constructor defined in your class then Java compiler will add a no parameter constructor in your generated class file. But if there is a constructor with parameter in your class, then you need to write the no-parameter constructor, compiler will not add it.
I want to make a helper class that deals with formatting (i.e. has methods to remove punctuation and convert between types, as well as reformatting names etc.). This doesn't seem like it will need any fields - its only purpose is to get passed things to convert and return them, reformatted. Is it bad practice to leave out a constructor? If so, what should my constructor be doing? I was looking at this link and noticed that the class it describes lacks a constructor.
Is it bad practice to leave out a constructor?
Yes - because unless you specify any constructors, the Java compiler will give you a constructor with the same visibility as the class itself.
Assuming all your methods are static - which seems likely unless you want polymorphism - you should make your class final and give it a private constructor, so that other developers don't accidentally create an instance of your class, when that would be pointless. When thinking about an API, any time I can remove the ability for developers to do something stupid, I do so :)
So something like:
public final class Helpers {
private Helpers() {
}
public static String formatDate(Date date) {
// etc
}
}
Note that by taking polymorphism out of the equation, you're also removing the possibility of changing this behaviour for tests etc. That may well be fine - I'm not a believer in "no statics, ever" - but it's worth considering.
Any class that has all the methods which do not have or need any state is free to reduce the visibility of constructor by making the constructor private.
Example java.lang.Math class in Java.
As java.lang.Math has all static methods which do similar job as your class they have declared the constructor as private so that nobody can accidentally create the instance of that class.
/**
* Don't let anyone instantiate this class.
*/
private Math() {}
Not bad practice. but the example that you have given doesn't have any member variables that can be used in an Object context. In such situations, it's best to have static methods because then you don't need to allocate memory to create objects for the class before calling the methods.
Compiler will generate a default constructor (with no parameters) for you. If your class has not state and does not extend a class which needs initialization, you can let it without declaring explicit constructor
no its good to leave out a constructor as there aren't any instance variables in your class!
constructors are meant to initialize the instance variables!
still if you skip the constructor, compiler anyways inserts the default constructor which is fair enough!!
You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.
Java Official Document: Providing Constructors for Your Classes
Usually it is a good coding practice to define your constructor in the class though each class has a default constructor .
But if you do not have any special need to use a oveloaded constructor or to make any singleton pattern then you can remove the constructor .
If you are using static methods in your case then also you dont have any need to define constructor , as you do not need to have object of this class .