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.
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.
There are too many associated names: Early and Late Binding, Static and Dynamic Dispatch, Runtime vs. Compile-time Polymorphism, etc. that I don't understand the difference.
I found a clear explanation, but is it correct? I'll paraphrase JustinC:
Binding: is determining the type of a variable (object?). If it's done at compile time, its early binding. If it's done at run time, it's late binding.
Dispatch: is determining which method matches the method call. Static Dispatch is computing methods at compile time, whereas dynamic dispatch is doing it at run time.
Is Binding matching up primitive and reference variables with primitive values and objects respectively?
Edit: Please give me some clear reference material so I can read more about this.
I believe the confusion typically comes from how overloaded these terms are.
We program our programs in a high level language, and either a compiler or an interpreter must transform that into something a machine actually understands.
In coarse terms, you can picture a compiler transforming our method code into some form of machine code. If the compiler knew at that point exactly where in the memory that method would reside when we run our program later, then it could safely go and find every method invocation of this compiled method and replace it with a jump to this address where the compiled code resides, right?.
Well, materializing this relationship is what I understand as binding. This binding, though, could happen at different moments, for example at compile time, linking time, load time, or at run time depending on the design of the language.
The terms static and dynamic are generally used to refer to things bound before run time and at run time, respectively.
Later binding times are associated with greater flexibility, earlier binding times are associated with greater efficiency. Language designers have to balance these two aspects when they're creating a language.
Most object-oriented programming languages support subtype polymorphism. In these languages, virtual methods are bound at runtime depending on the dynamic type of the object at that point. In other words, virtual method invocations are dispatched to the appropriate implementation at runtime based on the dynamic type of the object implementation involved and not based solely on its static type reference.
So, in my opinion, you must first bind the method invocation to a specific implementation or execution address, and then you can dispatch an invocation to it.
I had answered a very similar question in the past in which I demonstrate with examples how this happens in Java.
I would also recommend reading the book Programming Language Pragmatics. It is a great reference to learn all this kind of stuff from a theoretical standpoint.
When you're looking for "low level" definitions, probably the only legitimate source is our old friend - the JLS. Though it does not give a clear definition in this case, the context in which it uses each term might be enough.
Dispatch
This term is indeed mentioned in procedures of determining which method to call.
15.12.2. Compile-Time Step 2: Determine Method Signature
The second step searches the type determined in the previous step for
member methods. This step uses the name of the method and the argument
expressions to locate methods that are both accessible and applicable,
that is, declarations that can be correctly invoked on the given
arguments.
There may be more than one such method, in which case the
most specific one is chosen. The descriptor (signature plus return
type) of the most specific method is the one used at run time to
perform the method dispatch. A method is applicable if it is
applicable by one of strict invocation
The elaboration on what is the "most specific" method is done in 15.12.2.5 Choosing the Most Specific Method.
As for "dynamic dispatch",
JLS 12.5. Creation of New Class Instances:
Unlike C++, the Java programming language does not specify altered
rules for method dispatch during the creation of a new class instance.
If methods are invoked that are overridden in subclasses in the object
being initialized, then these overriding methods are used, even before
the new object is completely initialized.
It includes
Example 12.5-2. Dynamic Dispatch During Instance Creation
class Super {
Super() {
printThree();
}
void printThree() {
System.out.println("three");
}
}
class Test extends Super {
int three = 3;
void printThree() {
System.out.println(three);
}
public static void main(String[] args) {
Test t = new Test();
t.printThree();
}
}
Output:
0
3
This happens because during the constructor call chain, Super's constructor calls printThree, but due to dynamic dispatch the method in Test is called, and that is before the field is initialized.
Binding
This term is used in contexts of class member access.
Example 15.11.1-1. Static Binding for Field Access demonstrates early and late bindings. I will summarize the examples given there for the lazy of us:
class S {
int x = 0;
int z() { return x; }
}
class T extends S {
int x = 1;
int z() { return x; }
}
public class Test1 {
public static void main(String[] args) {
S s = new T();
System.out.println("s.x=" + s.x);
System.out.println("s.x=" + s.z());
}
}
Output:
s.x=0
s.x=1
Showing that the field uses "early binding", while the instance method uses "late binding":
This lack of dynamic lookup for field accesses allows programs to be run efficiently with
straightforward implementations. The power of late binding and overriding is available, but
only when instance methods are used.
Binding is also used in regards to determining the type of a generic,
8. Classes
Classes may be generic (§8.1.2), that is, they may declare type variables whose bindings may differ among different instances of the class.
Meaning that if you create 2 instances of List<String>, the bindings of String in both instances are different from each other.
This also applies to raw types:
4.8. Raw Types
class Outer<T>{
T t;
class Inner {
T setOuterT(T t1) { t = t1; return t; }
}
}
The type of the member(s) of Inner depends on the type parameter of Outer. If Outer is raw, Inner must be treated as raw as well, as there is no valid binding for T.
Meaning that declaring Outer outer (this will generate a raw type warning) does not allow to determine the type of T (obviously - it wasn't defined in the declaration).
These are general terms, you can summarize it in this way: when some thing(method or object) is static/early it means that thing is configured in compile-time and there is no ambiguity in run time for example in the following code:
class A {
void methodX() {
System.out.print("i am A");
}
}
If we create an instance of A and call methodX(), nothing is ambitious and everythin is configured at compile time but if we have the following code
class B extends A {
void methodX() {
System.out.print("i am B");
}
}
....
A objX= new B();
objX.methodX();
Out put of method x is not known until runtime, so this method is dynamically binded/dispatched (we can use the term dispatched instead of bind for methods link).
FXML-View:
....
<GridPane...>
<PersonController... />
</GridPane...>
....
Class PersonController:
public PersonController(Person... personsToExclude) {
FXMLLoader.load("PersonControllerView.fxml")
this.personsToExclude = personsToExclude;
}
This code sample leads to an excpetion, because the class cannot be invoked without a default constructor (by the FXMLLoader). Now my question: You CAN use this constructor as default constructor. You can create such an object like this:
PersonConstructor pc = new PersonConstructor(); // This calls the upper constructor
Why isn't reflection able to use this constructor too? Varargs appear to be arrays internally which will be null by default if no parameter was handed over.
Was this design decision solely made to reduce complexity (it actually does reduce it a little bit for the reader) or are there any other reasons why it is important to still have a "real" default constructor?
If Oliver Charlesworth is correct, your question is really:
Why doesn't Class#newInstance() work when the class doesn't have a zero-args constructor but does have a constructor accepting a single varargs argument?
If so, I don't think we can properly answer it unless there's a quote from the design process around adding varargs to Java.
We can speculate. My speculation is: Simplicity
newInstance() is older than varargs. Until varargs were added to the language, there was no ambiguity: It could only call the nullary (zero-arguments) constructor. So they may have felt that extending it to handle constructors accepting one varargs argument was code bloat and/or scope creep for the method. After all, if you really want to do that, you can look up the relevant constructor and call that instead.
Alternately, they may have felt that newInstance's documentation ruled out calling such a constructor. Let's look at the JavaDoc for newInstance():
Creates a new instance of the class represented by this Class object. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized.
Note that this method propagates any exception thrown by the nullary constructor, including a checked exception...
The first paragraph supports the idea that it could call a constructor with just one varargs argument. The second paragraph, though, mentions a "nullary" constructor specifically (though in passing). A "nullary" constructor is a zero-argument constructor, specifically, not just a constructor that can be called with no arguments.
Doing so would markedly complicate newInstance(), because rather than just looking for a constructor that accepts no arguments, it would need to look through all the constructors for one that accepts a single argument where isVarArgs is true.
Changing newInstance() to do what you're suggesting adds a new error mode: It's perfectly possible for your PersonConstructor class to have more than one constructor that can be called via new PersonConstructor():
public class PersonConstructor
{
public PersonConstructor(String... args) {
}
public PersonConstructor(Person... args) {
}
}
So which one should newInstance call? It can't decide, so it would have to throw, throwing a new error it hadn't thrown prior to the addition of varargs to the language.
All in all, if I were on the team making the decision, I would also have had newInstance() only consider true nullary constructors and not constructors accepting a single varargs argument. (I would also have updated the JavaDoc to say that. :-) )
Variable argument lists are implemented entirely in the compiler. Methods that take arrays and methods that take vararg arrays are compatible with each other - for example, you can use vararg signature
void foo(String... args)
to override a non-vararg signature
void foo(String[] args)
and vice versa (demo).
Was this design decision solely made to reduce complexity?
It is hard to guess why this particular design decision has been made, but at least part of the reason can be attributed to designer's reluctance to make changes to libraries and JVM. Java 5 update, in which variable argument feature has been introduced, opted for full backward compatibility on the bytecode level, despite the fact that it was a very big update, which introduced generics.
If you would like to work around this limitation, implement a no-argument constructor that routs the call to the constructor which takes an array:
public PersonController(Person... personsToExclude) {
}
public PersonController() {
this(new Person[0]);
}
Varargs appear to be arrays internally which will be null by default if no parameter was handed over.
This is not true. If you call a vararg method (or constructor) without any argument, the method (or constructor) is still a method with one array argument. And not null will be passed, but an empty array, as Oliver already has pointed out.
So the answer is: A vararg constructor has definitely one argument, and so it cannot be a default constructor.
I had a test today and one of the questions was about using a virtual method in C++ constructor. I failed this question, I answered that there shouldn't be any problem, however after reading this I found out I was wrong.
So I understand that the reason for not allowing that is because the derived object is not fully initialized and therefore calling it's virtual method can cause invalid consequences.
My question how was it solved in Java/C# ? I know that I can call derived method in my base constructor, I would assume that these languages have exactly the same problem.
Java has a very different object model from C++. In Java, you cannot have variables which are objects of class type -- instead, you can only ever have references to objects (of class type). Therefore, all members of a class (which are only references) start out trivially as null until the entire derived object has been set up in memory. Only then do the constructors run. Thus by the time a base constructor calls a virtual function, even if that function is overridden, the overridden function can at least correctly refer to members of the derived class. (Those members may not themselves be assigned yet, but at least they exist.)
(If it helps, you can also consider that every class without final members in Java is technically default-constructible, at least in principle: Unlike in C++, Java has no such things as constants or references (which must be initialized in C++), and in fact there are no initializer lists at all. Variables in Java simply don't need to be initialized. They're either primitives which start as 0, or class type references which start as null. One exception comes from non-static final class members, which cannot be rebound and must actually be "initialized" by having precisely one assignment statement somewhere in every constructor [thanks to #josefx for pointing this out!].)
understand that the reason for not allowing that is because the derived object is not fully initialized and therefore calling it's virtual method can cause invalid consequences
Wrong. C++ will call the base class's implementation of the method, not the derived class's. There are no 'invalid consequences'. The only valid reason for avoiding the construct is that the behavior sometimes comes as a surprise.
This is different from Java because Java calls the derived class's implementation.
In C++ every polymorphic class( class that has at least one virtual function ) has a hidden pointer at start of it( usually named v-table or something like that ) that will be initialized to the virtual table( an array of functions that point to the body of each virtual function ) of that class and when you call a virtual function C++ simply call ((v-table*)class)[index of your function]( function-parameters ), so if you call a virtual function in base class constructor v-table point to virtual table of the base class since your class is base and it still need some initialization to become child and as a result you will call implementation of the function from base not from child and if this is a pure virtual function you will get an access violation.
but in java this is not something like this, in java whole the class is something like std::map<std::string, JValue> in this case JValue is some variant type( for example a union or boost::variant ) when you call a function in constructor of base it will find function name in the map and call it, it is still not the value from the child but you can still call it and if you changed it in the prototype, since prototype created before your constructor you can successfully call function from child but if function required some initialization from constructor of the child you still get error or an invalid result.
so in general it is not a good practice to call a function from child( for example a virtual function ) in base class. if your class need to do this add an initialize method and call it from constructor of your child class.
Every Java constructor looks like this:
class Foo extends Bar {
Foo() {
super(); // creates Bar
// do things
}
}
So if you place code working on derived methods in do things, seems to be logic, that this base object was initialized properly, after calling its constructor in super();
I think that Java/C# avoid this problem by constructing from derived class backwards rather than in C++ from base class forwards.
Java implicitly calls super() in a classes constructor so by the time the first line of written code in a derived class constructor is called all the constructors of all inherited classes are guaranteed to have been called and so the new instance will have been completely initialised.
I think also in C++ a new instance of a class begins life as the base class and gets "upgraded" to the final class type as we move down the inheritance chain. This means that when you call a virtual function in the constructor you'll actually be calling the version of that function for the base class.
In Java and presumably C# a new instance starts life as the required class type so the correct version of the virtual method will be called.
Java does not entirely avoid the problem.
An overridden method called from a superclass constructor that depends on fields of the subclass will be called before those fields have been initialized.
If you're in control of the entire class hierarchy, you can of course just make sure your overrides don't depend on subclass fields. But it's safer to just not call virtual methods from constructors.
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