Actual use of default constructor in java - java

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.

Related

Is it possible to disable injection of implicit constructor methods/calls?

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

Completing work in constructor VS using an initializer

From what I have seen in other peoples code, there appears to be two ways common ways in creating an object and "readying" it to be used.
Method 1: Ready the object in the constructor:
public class SomeClass {
int setting;
public SomeClass(int setting) {
this.setting = setting;
}
}
Method 2: Create the Object then "ready" it inside an initialize method such as:
public class SomeClass {
int setting;
public SomeClass(int setting) {
}
public void init(int setting) {
this.setting = setting;
}
}
Is there any specific reason to use either method over another?
One reason for using the constructor is that you can make the field final - immutability isn't an option if you the constructed object isn't fully initialized. Personally I prefer to write code so that by the time an object is available, it's really ready to use - rather than having life-cycles of "construct, initialize, use".
On the other hand, doing a lot of work in a constructor is also generally frowned upon - partly because during construction you're potentially in an odd state as any subclasses won't have run their constructor bodies yet, so calling overridden methods in constructors is a bad idea.
Another alternative is to have a static method which does most of the actual work, and then delegates to a constructor just passing in field values. Factory methods like this have additional benefits such as the ability to return null where appropriate (rare, but it happens) or reuse existing objects.
As per the codes in your question:
Whenver you use setting and want it to be initialized you need to use the argument constructor SomeClass(int setting) like:
SomeClass someClass=new SomeClass(12);
And in the second case you need to call the method by passing the argument to get it initialised as in:
SomeClass someClass=new SomeClass(6);
someClass.init(6);
This depends on your requirement ,however initializing a variable using a constructor is mostly preferred.
Yes, as these 2 approaches give different behaviour, hence one may be preffered over the other:
In 2nd approach, class members are automatically initialized by the compiler using the default constructor, unless you call init method and set the values to your required initial values.
So, setting will be 0 by default when the object is created. Now, if you do not call init() on the newly created object and use it in your program, this may lead to undesirable behaviour. This is the reason the constructor approach is preffered.
However, placing too much code in constructor may lead to poor responsiveness, and also produces undesired results in case of inheritence. For such reasons, First approach is not preffered in general.

Explicit constructor still has default values even though a default constructor is not invoked.

According to my understanding a default constructor initializes the state of the object to default values, so if i provide an explicit no-arg public constructor like this then how are the values of d and e still getting initialized to zero because in this case the default constructor is not invoked.
public class B extends A{
private int d;
private int e;
public B() {
System.out.println(d);
System.out.println(e);
}
}
EDIT:: The only thing default constructor does is call to super() then how come if i have a explicitly mentioned a constructor here and A has a protected variable say c which is initialized to 17 in its constructor. Should I not be explicitly calling super() to be able to see that change since I'm using my own constructor ? Why is B still getting the value of 17 through inheritance ?
All class fields get assigned default values if you don't explicitly initialize them on declaration, in a initializer block, or in your constructor. Objects get initialized to null, ints to 0, booleans to false, doubles to 0.0, float to 0.0f, long to 0L, char to '\u0000`...
Please see the JLS, section 4.12.5. Initial Values of Variables as it explains it all.
Note that these rules do not apply to variables that are local to any block or method, but instead local variables must be initialized explicitly by the coder before use.
Edit
Regarding your edit:
The only thing default constructor does is call to super() then how come if i have a explicitly mentioned a constructor here and A has a protected variable say c which is initialized to 17 in its constructor. Should I not be explicitly calling super() to be able to see that change since I'm using my own constructor ? Why is B still getting the value of 17 through inheritance ?
Answer: The super() default constructor is being called at the very beginning of B's constructor, whether you explicitly call it or not. The only extra benefit obtained by explicitly calling the super constructor here does is to allow you to call a non-default constructor for A, if one exists, and if you so desire.
Since you have used primitive type of data members so they are defaulted to values as per language specifications and in this case with values you would have chosen.
You can use constructor to initialize all the members of your class which you don't want to be defaulted as per specification (like Objects gets null values by default).
Its simple , the variables get their default values as you are not initialising them.
The default value is 0 for integers

State of Derived class object when Base class constructor calls overridden method in Java

Please refer to the Java code below:
class Base{
Base(){
System.out.println("Base Constructor");
method();
}
void method(){}
}
class Derived extends Base{
int var = 2;
Derived(){
System.out.println("Derived Constructor");
}
#Override
void method(){
System.out.println("var = "+var);
}
}
class Test2{
public static void main(String[] args) {
Derived b = new Derived();
}
}
The output seen is:
Base Constructor
var = 0
Derived Constructor
I think var = 0 occurs because Derived object is half initialized; similar to what Jon Skeet says here
My questions are:
Why does the overridden method get called if the Derived class object isn't created yet?
At what point in time is var assigned value 0?
Are there any use cases where such behavior is desired?
The Derived object has been created - it's just that the constructor hasn't been run yet. The type of an object never changes in Java after the instant it is created, which happens before all constructors run.
var is assigned the default value of 0 as part of the process of creating an object, before constructors are run. Basically, the type reference gets set and the rest of the memory representing the object gets wiped to zero (conceptually, anyway - it may already have been wiped to zero before, as part of garbage collection)
This behaviour at least leads to consistency, but it can be a pain. In terms of consistency, suppose you had a read-only subclass of a mutable base class. The base class may have an isMutable() property which was effectively defaulted to true - but the subclass overrode it to always return false. It would be odd for the object to be mutable before the subclass constructor ran, but immutable afterwards. On the other hand, it's definitely strange in situations where you end up running code in a class before the constructor for that class has run :(
A few guidelines:
Try not to do much work in a constructor. One way of avoiding this is to do work in a static method, and then make the final part of the static method a constructor call which simply sets fields. Of course, this means you won't get the benefits of polymorphism while you're doing the work - but doing so in a constructor call would be dangerous anyway.
Try very hard to avoid calls to non-final methods during a constructor - it's very likely to cause confusion. Document any method calls you really have to make very clearly, so that anyone overriding them knows that they will be called before initialization has finished.
If you have to call a method during construction, it's usually not then appropriate to call it afterwards. If that's the case, document it and attempt to indicate it in the name.
Try not to overuse inheritance in the first place - this is only going to become an issue when you've got a subclass deriving from a superclass other than Object :) Designing for inheritance is tricky.
Why does the overridden method get
called if the Derived class object
isn't created yet?
Derived class constructor implicitly calls the Base class constructor as the first statement. Base class constructor calls method() which invokes the overridden implemention in the Derived class because that is the class whose object is being created. method() in Derived class sees var as 0 at that point.
At what point in time is var assigned
value 0?
var is assigned the default value for int type i.e. 0 before the contructor of Derived class is invoked. It gets assigned the value of 2 after the implicit superclass contructor call has finished and before the statements in Derived class's constructor start executing.
Are there any use cases where such
behavior is desired?
It is generally a bad idea to use non-final non-private methods in the constructors/initializers of a non-final class. The reasons are evident in your code. If the object that is being created is a subclass instance, the methods may give unexpected results.
Note that this is different from C++, where the type does change while the object is being constructed, so that calling a virtual method from the base class constructors doesn't call the derived class's override. The same thing happens in reverse during destruction. So this can be a small trap for C++ programmers coming to Java.
There are some properties of the Java language specification that should be noted in order to explain this behavior:
A superclass' constructor is always implicitely/explicitely called before a subclass' constructor.
A method call from a constructor is just like any other method call; if the method is a non-final, then the call is a virtual call, meaning that the method implementation to invoke is the one associated with the runtime type of the object.
Prior to a constructor execution, all data members are automatically initialized with default values (0 for numeric primitives, null for objects, false for boolean).
The sequence of events is as follows:
An instance of the subclass is created
All data members are initialized with default values
The constructor being invoked immediately delegates control to the relevant superclass' constructor.
The super constructor initializes some/all of its own data members, and then calls a virtual method.
The method is overriden by the subclass, so the subclass implementation is invoked.
The method tries to use the subclass' data members, assuming they are already initialized, but this is not the case - the call stack hasn't returned to the subclass' constructor yet.
In short, whenever a constructor of a superclass invokes a non-final method, we have the potential risk of entering into this trap, therefore doing it is not recommended.
Note that there is no elegant solution if you insist on this pattern. Here are 2 complex and creative ones, both requiring thread synchronization(!):
http://www.javaspecialists.eu/archive/Issue086.html
http://www.javaspecialists.eu/archive/Issue086b.html

C++ vs Java constructors

According to John C. Mitchell - Concepts in programming languages,
[...] Java guarantees that a
constructor is called whenever an
object is created. [...]
This is pointed as a Java peculiarity which makes it different from C++ in its behaviour. So I must argue that C++ in some cases does not call any constructor for a class even if an object for that class is created.
I think that this happens when inheritance occurs, but I cannot figure out an example for that case.
Do you know any example?
If your class defines at least one constructor, then the language will not allow you to construct an object of that type without calling a constructor.
If your class does not define a constructor, then the general rule is that the compiler-generated default constructor will be called.
As other posters have mentioned, if your class is a POD type, there are cases where your object will be left uninitialized. But this is not because the compiler "didn't call the constructor". It is because the type has no constructor (or it has one which does nothing), and is handled somewhat specially. But then again, POD types don't exist in Java, so that can't really be compared.
You can also hack around things so that the constructor is not called. For example, allocate a buffer of char's, take a pointer to the first char and cast it to the object type. Undefined behavior in most cases, of course, so it's not really "allowed", but the compiler generally won't complain.
But the bottom line is that any book which makes claims like these without being very explicit about which specific corner cases they're referring to, is most likely full of garbage. Then again, most people writing about C++ don't actually know much about the language, so it shouldn't be a surprise.
There are two cases in Java (I'm not aware of any more) in which a class' may be constructed without its constructor being called, without resulting to hacking in C or similar:
During deserialisation, serialisable classes do not have their constructor called. The no-arg constructor of the most derived non-serialisable class is invoked by the serialisation mechanism (in the Sun implementation, through non-verifiable bytecode).
When the evil Object.clone is used.
So the claim that constructors are always called in Java, is false.
For C++ types that declare constructors, it is not possible to create instances of those types without the use of a constructor. For example:
class A {
public:
A( int x ) : n( x ) {}
private:
int n;
};
it is not posible to create instancev of A without using the A(int) constructor, except by copying, which in this instance will use the synthesised copy constructor. In either case, a constructor must be used.
Java constructors can call another constructor of the same class. In C++ that is impossible. http://www.parashift.com/c++-faq-lite/ctors.html
POD's (plain old data types) are not initialized via constructors in C++:
struct SimpleClass {
int m_nNumber;
double m_fAnother;
};
SimpleClass simpleobj = { 0 };
SimpleClass simpleobj2 = { 1, 0.5 };
In both cases no constructor is called, not even a generated default constructor:
A non-const POD object declared with no initializer has an "indeterminate initial value".
Default initialization of a POD object is zero initialization.
( http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html )
If however, SimpleClass itself defined a constructor, SimpleClass would not be a POD anymore and one of the constructors would always be called.
In C++, when an object is instantiated, a constructor of that class must be called.
There are particular cases in C++ where a constructor will not be called. In particular for POD types the implicitly defined default constructor will not be called in some situations.
struct X {
int x;
};
int main() {
X x; // implicit default constructor not called
// No guarantee in the value of x.x
X x1 = X(); // creates a temporary, calls its default constructor
// and copies that into x1. x1.x is guaranteed to be 0
}
I don't quite remember the whole set of situations where that can happen, but I seem to recall that it was mostly in this case.
To further address the issue:
This is pointed as a Java peculiarity which makes it different from C++ in its behaviour. So I must argue that C++ in some cases does not call any constructor for a class even if an object for that class is created.
Yes, with POD types you can instantiate objects and no constructor will be called. And the reason is
This is of course done for compatibility with C.
(as Neil comments out)
I think that this happens when inheritance occurs, but I cannot figure out an example for that case.
This has nothing to do with inheritance, but with the type of object being instantiated.
Java can actually allocate objects without(!) calling any constructor.
If you browse the sources of ObjectInputStream you will find that it allocates the deserialized objects without calling any constructor.
The method which allows you to do so is not part of the public API, it is in a sun.* package. However, please don't tell me it is not part of the language because of that. What you can do with public API is put together the byte stream of a deserialized object, read it in and there you go with an instance of the object whose constructor was never called!
Giving an interpretation, I have a suggestion about why the author says that for Java, without looking for any corner cases which I think don't address really the problem: you could think for example that PODs are not objects.
The fact that C++ has unsafe type casts is much more well known. For example, using a simple mixture of C and C++, you could do this:
class A {
int x;
public:
A() : X(0) {}
virtual void f() { x=x+1; }
virtual int getX() { return x; }
};
int main() {
A *a = (A *)malloc(sizeof(A));
cout << a->getX();
free(a);
}
This is a perfectly acceptable program in C++ and uses the unchecked form of type cast to avoid constructor invocation. In this case x is not initialized, so we might expect an unpredictable behaviour.
However, there might be other cases in which also Java fails to apply this rule, the mention of serialized object is perfectly reasonable and correct, even though you know for sure that the object has already been constructed in some way (unless you do some hacking on the serialized encoding of course).
Only When you overload new operator function then constructor is not called (it used to avoid constructor calling), else its in standard that constructor is invoked when object is created.
void * operator new ( size_t size )
{
void *p = malloc(size);
if(p)
return p;
else
cout<<endl<<"mem alloc failed";
}
class X
{
int X;
};
int main()
{
X *pX;
pX = reinterpret_cast<X *>(operator new(sizeof(X)*5)); // no ctor called
}
As far as I remember, Meyers in his "Effective C++" says, that the object is ONLY created when the control flow has reached his constructor's end. Otherwise it is not an object. Whenever you want to mistreat some raw memory for an actual object, you can do this:
class SomeClass
{
int Foo, int Bar;
};
SomeClass* createButNotConstruct()
{
char * ptrMem = new char[ sizeof(SomeClass) ];
return reinterpret_cast<SomeClass*>(ptrMem);
}
You won't hit any constructors here, but you may think, that you are operating a newly created object (and have a great time debugging it);
Trying to make things clear about C++. Lots of imprecise statements in answers.
In C++, a POD and a class behave the same way. A constructor is ALWAYS called. For POD, the default constructor does nothing: it does not initializes the value. But it is an error to say that no constructor is called.
Even with inheritance, constructors are called.
class A {
public: A() {}
};
class B: public A {
public: B() {} // Even if not explicitely stated, class A constructor WILL be called!
};
This seems comes down to defining the term "object" so that the statement is a tautology. Specifically, with respect to Java, he's apparently defining "object" to mean an instance of a class. With respect to C++, he (apparently) uses a broader definition of object, that includes things like primitive types that don't even have constructors.
Regardless of his definitions, however, C++ and Java are much more alike than different in this respect. Both have primitive types that don't even have constructors. Both support creation of user defined types that guarantee the invocation of constructors when objects are created.
C++ does also support creation (within very specific limits) of user defined types that don't necessarily have constructors invoked under all possible circumstances. There are tight restrictions on this, however. One of them is that the constructor must be "trivial" -- i.e. it must be a constructor that does nothing that was automatically synthesized by the compiler.
In other words, if you write a class with a constructor, the compiler is guaranteed to use it at the right times (e.g. if you write a copy constructor, all copies will be made using your copy constructor). If you write a default constructor, the compiler will use it to make all objects of that type for which no initializer is supplied, and so on.
even in the case we use statically allocated memory buffer for object creation , constructor is called.
can be seen in the following code snippet.
i haven't seen any general case yet where constructor is not called, but then there is so much to be seen :)
include
using namespace std;
class Object
{
public:
Object();
~Object();
};
inline Object::Object()
{
cout << "Constructor\n";
};
inline Object::~Object()
{
cout << "Destructor\n";
};
int main()
{
char buffer[2 * sizeof(Object)];
Object *obj = new(buffer) Object; // placement new, 1st object
new(buffer + sizeof(Object)) Object; // placement new, 2nd object
// delete obj; // DON’T DO THIS
obj[0].~Object(); // destroy 1st object
obj[1].~Object(); // destroy 2nd object
}
In Java there are some situations when the constructor is not called.
For example when a class is deserialized, the default constructor of the first non-serializable class in the type hierarchy will be called, but not the constructor of the current class. Also Object.clone avoids calling the constructor. You can also generate bytecode and do it yourself.
To understand how this is possible, even without native code magic inside the JRE, just have a look at the Java bytecode. When the new keyword is used in Java code, two bytecode instructions are generated from it - first the instance is allocated with the new instruction and then the constructor is called with the invokespecial instruction.
If you generate your own bytecode (for example with ASM), it's possible change the invokespecial instruction to call the constructor of one of the actual type's super classes' constructor (such as java.lang.Object) or even completely skip calling the constructor. The JVM will not complain about it. (The bytecode verification only checks that each constructor calls its super class's constructor, but the caller of the constructor is not checked for which constructor is called after new.)
You can also use the Objenesis library for it, so you don't need to generate the bytecode manually.
What he means is in Java, constructor of the super class is always called. This is done by calling super(...), and if you omit this compiler will insert one for you. Only exception is one constructor calls another constructor. In that case other constructor should call super(...).
This automatic code insertion by the compiler is strange actually. And if you do not have super(...) call, and the parent class does not have a constructor with no parameter it will result in a compile error. (It is odd to have a compile error for something that is automatically inserted.)
C++ will not do this automatic insertion for you.

Categories

Resources