In Java, from where can a constructor be invoked? - java

Is this statement true or false?
"The only way a constructor can be invoked is from within another constructor."
I thought a constructor could be invoked from within a method (and other places) if the call to the constructor is preceded with the keyword 'new'.
How about this statement? True or false?
"The only way a constructor can be invoked is from within another constructor (using a call to super() or this()), or from within static or instance methods, static or instance initializer blocks, or even constructors, if the call to the constructor is preceded by the keyword 'new'." Trying to invoke a constructor like you would invoke a method (using only its name) is not allowed."
Is this more accurate? "Where the call to the constructor is not preceded by the keyword 'new', the only way a constructor can be invoked is from within another constructor using this() or super() as the first statement."

Let's just go straight to the JLS, §8.8:
Constructors are invoked by class instance creation expressions (§15.9), by the conversions and concatenations caused by the string concatenation operator + (§15.18.1), and by explicit constructor invocations from other constructors (§8.8.7). [...]
Constructors are never invoked by method invocation expressions (§15.12).
Therefore, the first statement you quoted is technically false, as the JLS defines using new as invoking the constructor.
Note that your paragraph-length statement is a combination of true and false information; you can't invoke a constructor from static or instance methods except via creating a new object.

Rather than focusing on what the author of the original questions means by "invoke"1, here are the different ways that a constructor will be called.
By using the new operator with the class name and parameters that match the constructor signature:
Foon f = new Foon(1, 2);
It is also possible to do the same thing using reflection and the Constructor object equivalent to a new expression, or by using the relevant JNI or JNA callbacks in native code equivalent to a new expression. However, in all cases, the constructor invocation is conceptually happening at same point in the object creation. Hence I will treat them as identical.
By explicitly chaining to the constructor from another constructor in the same class using this(...).
By explicitly chaining to the constructor from a direct subclass constructor using super(...), or by implicitly chaining to a no-args constructor via an implied super() in a direct subclass constructor (declared or implied).
The implicit cases are merely "syntactic sugar" for the explicit super chaining cases.
There are a few other places where new is invoked behind the scenes by Java from regular Java code. A couple that spring to mind are string concatenation, auto-boxing, and the JVM throwing certain exceptions; e.g.
null.toString() // implicitly creates a NullPointerException obj.
1 - ... which is unknowable unless we understand the context, including how the OP's lecturer (or text book) is using the word "invoke".

It's true. You can't write code that actually calls a constructor as follows:
class Vehicle {
Vehicle() { } // Constructor
void doSomething() {
Vehicle(); // Illegal
}
}

The famous illusive constructor.
It's there when it's there, and even when it's not there it's still there.
The constructor is called at object creation.
So yeah the constructor can, or more precisely will be called if you create a object using new , na matter where you use it.
That quote of yours seems to be incomplete
"The only way the constructor of the superclass of the current class can be invoked is from within the current class constructor."

You can use the constructor when you use the class as an object in other class.
MyClass mc = new MyClass();

This statement is false.
'Invoking a constructor' can mean three different things:
You can invoke a constructor by creating a new object with the new operator:
String s = new String("abc");
In which case you will first allocate an object and then invoke the constructor:
NEW java/lang/String // allocate String instance
LDC "abc" // push the String constant on the stack
INVOKESPECIAL "java/lang/String"."<init>" : "(Ljava/lang/String;)V" // invoke constructor
The second way is to invoke another constructor from the same class:
class Super
{
Super(int i) { }
}
class Test extends Super {
Test() { this(1); }
// Bytecode:
INVOKESPECIAL "Test"."<init>" : "(I)V"
// ---------
The third way to invoke a constructor is to invoke one from the super class:
Test(int i) { super(i); }
// Bytecode:
INVOKESPECIAL "Super"."<init>" : "(I)V"
// ---------
}
Either way, the generated bytecode will contain an INVOKESPECIAL instruction. This means you are literally invoking the constructor in three cases, so if you define 'invoke' by that instruction, there is more than one way to invoke a constructor.

If you mean, directly invoking another constructor of the same object using the this(...) or super(...) construct (called explicit constructor invocation), the answer is yes.
It is probable that this is what the question meant but you have to be really precise in the wording and this question isn't.
Because if by "invoke" you mean, "causing a constructor to run", then you can "invoke" a constructor with the new keyword, which first allocates and creates the object, and then a constructor is run. In this, rather looser sense the answer is no.
But, importantly, new does a lot more than just calling the constructor. So in the most literal sense, calling new is not the same as invoking a constructor. Just like making tea involves pouring hot water but is not the same as simply pouring hot water.
Whether you want to make that distinction or not is up to you, or in this case the author of the question, you need to ask them.

Related

What is the purpose of calling the constructor of the object class in Java?

Take this simple class...
public class Gen
{
public static void main (String[] Args)
{
Gen genny = new Gen();
}
}
Section 8.8.9 of the JLS states that "If a class contains no constructor declarations, then a default constructor is implicitly declared." It also says that as long as we're not in the java.lang.object class, then the "default constructor simply invokes the superclass constructor with no arguments."
So because the class Gen extends java.lang.object, we are forced to call java.lang.object's constructor through super() as part of the implicitly-created default constructor.
Likewise...
public class Gen extends Object
{
public static void main (String[] Args)
{
Gen genny = new Gen();
}
public Gen()
{
}
}
Even if we explicitly declare a constructor for Gen, Section 8.8.7 of the JLS mandates that "if a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments."
So once again, Java is going above and beyond to get us to call java.lang.object's constructor through super(). But java.lang.object's constructor literally has an empty body. It doesn't do anything. A constructor has actual purpose only 1) if you write it such that it initializes a class' instance variables or 2) if it directly/indirectly calls its superclass(es)'s constructors to initialize their instance variables. java.lang.object's constructor does neither of these things because it 1) has no instance variables and 2) is the root of the inheritance hierarchy. So it's a pointless constructor. And now, in our class Gen, we are being pointlessly forced to call a pointless constructor.
Why do this? Why can't the Java people just say "right, if the class is a direct subclass of java.lang.object then we won't implicitly define a constructor and neither will we implicitly call super() if a constructor explicitly exists." Honestly, why even have a constructor for java.lang.object in the first place if it's gonna be empty?
First of all, it is NOT necessary to write this:
public class Gen extends Object {
If a class doesn't explicitly have some other class as its direct superclass, then it implicitly extends Object. There is not need to tell the compiler that.
Yes ... all classes (apart from Object) constructors will call a constructor of their superclass. Even if the superclass is Object.
But it doesn't matter to the programmer. As the spec says, if the constructor to be called is a no-args constructor, then you don't need an explicit super call. The compiler injects a missing super() call for you if you don't include one.
Yes ... the Object constructor has an empty body in all Java implementations I have come across.
But I don't think that the JLS mandates that.
The JLS section on how objects are created states that the constructor will be called.
But it doesn't say that the compilers can't optimize away the call to the Object() constructor. And that is what they do. (The bytecode compiler is required to emit instructions for the call by JVM spec, but the JIT compiler can and will optimize it away.)
Why do they specify it in these terms?
Primarily because the spec is easier to understand and the language is easier to use if there are fewer special cases in the Java syntax and semantics.
"You can't have a super() class if the superclass is Object" would be a special case. But this complexity is not needed to make the language work, and it certainly doesn't help programmers if you force them to leave out a super() call in this context.
In addition, the current way permits a Java implementation to have a non-empty Object() constructor, if there was a good reason for doing that. (But I doubt that that was serious consideration when they designed Java.)
Either way, this is the way that Java has been since before Java 1.0, and they won't change it now. The current way doesn't actually cause any problems, or add any appreciable overheads.

Does a Java constructor return the Object reference?

I know Java's constructors can't have any type and interestingly it cannot even be void. A logical explanation for that would be that a constructor returns the initialized object's reference.
MyClass myObject = new MyClass();
The constructor of myClass will now return the object reference after instantiating it and save it in the object variable MyObject and that's why the constructor can't have a return type.
Is that right? Could someone confirm this?
No, actually, the constructors are compiled into the class file like methods having the name <init> and a void return type. You can see these "<init>" invocations in stack traces. The expression new Type() is compiled as an instruction new which just creates the instance of Type and an additional method invokation (invokespecial) to one of the constructors declared in Type.
The verifier will ensure that such a special method is invoked at exactly once on a newly created instance and that it is called before any other use of the object.
It’s just a programming language design decision to let constructors have no return type from the Java language point of view. After all, new Type(…) is an expression that evaluates to the newly created instance of Type and you can’t get a return value from the constructor with that programming language construct. Further, if you add a return type, Java will unconditionally assume that it is a method, even if it has the same name as the class.
That’s simply how it was defined: (It makes parsing the class definition easier)
The SimpleTypeName in the ConstructorDeclarator must be the simple name of the class that contains the constructor declaration, or a compile-time error occurs.
In all other respects, a constructor declaration looks just like a method declaration that has no result (§8.4.5).
I suppose you could say that constructors have a "special syntax" used specifically for returning instances of the desired object. You do not specify the return type in these cases. The new keyword is used together with the constructor method to produce an instance of the class type.
If you'd like to control the return type of an instance generation method, then you should probably be looking at using a type of factory design pattern, wherein a static method creates an instance (using a constructor), and then returns a more explicit type (say for example, the super type, or an interface type).
This pattern is good when you'd like to decide which type to return based on some parameter, but leave the actual type hidden to the consumer of the instance generation method.
A constructor is not a methed. It does not return anything. It is used for initialization purposes, especially useful when those initializations depend on parameters or there is a chance that exceptions will be thrown (though both are optional).
So, unlike a method, it is not inherited and does not have a return type (not even void).
The idea is that you are "constructing" an instance of MyClass by calling the constructor itself. The idea of the constructor is to instantiate and not to return. Having created myObject you can then refer to public methods and variables part of its declaration which will provide you with the required data being returned as an answer to a call. It is important to understand that the constructor does not return anything it simply creates an instance which can then be used to refer to methods and variables (which return data) declared within the instantiated class.

A call to a static method within the parameter list of super() is valid in Java. Why?

Let's look at the following code snippet in Java.
package trickyjava;
class A
{
public A(String s)
{
System.out.println(s);
}
}
final class B extends A
{
public B()
{
super(method()); // Calling the following method first.
}
private static String method()
{
return "method invoked";
}
}
final public class Main
{
public static void main(String[] args)
{
B b = new B();
}
}
By convention, the super() constructor in Java must be the first statement in the relevant constructor body. In the above code, we are calling the static method in the super() constructor parameter list itself super(method());.
It means that in the call to super in the constructor B(), a method is being
called BEFORE the call to super is made! This should be forbidden by the compiler but it works nice. This is somewhat equivalent to the following statements.
String s = method();
super(s);
However, it's illegal causing a compile-time error indicating that "call to super must be first statement in constructor". Why? and why it's equivalent super(method()); is valid and the compiler doesn't complain any more?
The key thing here is the static modifier. Static methods are tied to the class, instance methods (normal methods) are tied to an object (class instance). The constructor initializes an object from a class, therefore the class must already have been fully loaded. It is therefore no problem to call a static method as part of the constructor.
The sequence of events to load a class and create an object is like this:
load class
initialize static variables
create object
initialize object <-- with constructor
object is now ready for use
(simplified*)
By the time the object constructor is called, the static methods and variables are available.
Think of the class and its static members as a blueprint for the objects of that class. You can only create the objects when the blueprint is already there.
The constructor is also called the initializer. If you throw an exception from a constructor and print the stack trace, you'll notice it's called <init> in the stack frame. Instance methods can only be called after an object has been constructed. It is not possible to use an instance method as the parameter for the super(...) call in your constructor.
If you create multiple objects of the same class, steps 1 and 2 happen only once.
(*static initializers and instance initializers left out for clarity)
Yep, checking the JVM spec (though admittedly an old one):
In the instance init method, no reference to "this" (including the implicit reference of a return) may occur before a call to either another init method in the same class or an init method in the superclass has occurred.
This is really the only real restriction, so far as I can see.
The aim of requiring the super constructor to be invoked first is to ensure that the "super object" is fully initialized before it is used (It falls short of actually enforcing this because the super constructor can leak this, but that's another matter).
Calling a non-static method on this would allow the method to see uninitialized fields and is therefore forbidden. A static method can only see these fields if it is passed this as argument. Since accessing this and super is illegal in super constructor invocation expressions, and the call to super happens before the declaration of any variables that might point to this, allowing calls to static methods in super constructor invocation expressions is safe.
It is also useful, because it allows to compute the arguments to the super constructor in an arbitrarily complex manner. If calls to static methods weren't allowed, it would be impossible to use control flow statements in such a computation. Something as simple as:
class Sub extends Super {
Sub(Integer... ints) {
super(Arrays.asList(ints));
}
}
would be impossible.
This is one situation where the java syntax hides what's really going on, and C# makes it a bit clearer.
In C# your B would look like
class B : A {
public B() : base(method()) {
}
private static String method() {
return "method invoker";
}
}
Although the java syntax places super(method) within the constructor it's not really called there: All the parent initialization is run before your subclass constructor. The C# code shows this a little more clearly; by placing super(method()) at the first line of the java constructor you're simply telling java to use the parameterized constructor of the super class rather than the parameterless version; this way you can pass variables to the parent constructor and they'll be used in the initialization of the parent level fields before your child's constructor code runs.
The reason that super(method()) is valid (as the first line in a java constructor) is because method() is being loaded with the static elements--before the non-static ones, including the constructors--which allows it to be called not only before B(), but before A(String) as well. By saying
public B() {
String s = method();
super(s);
}
you're telling the java compiler to initialize the super object with the default constructor (because the call to super() isn't the first line) and you're ready to initialize the subclass, but the compiler then becomes confused when it sees that you're trying to initialize with super(String) after super() has already run.
A call to super is a must in java to allow the parent to get initalized before anything with child class starts.
In the case above, if java allows String s= method(); before the call to super, it opens up flood gate of things that can be done before a call to super. that would risk so many things, essentially that allows a half baked class to be used. Which is rightly not allowed. It would allow things like object state (some of which may belong to the parent) being modified before it was properly created.
In case of super(method()); call, we still adhere to the policy of completing parent initialization before child. and we can use a static member only, and static member of child classes are available before any child objects are created anyways. so the method is avilable and can be called.
OK..i think, this one could be relevant that, if we are calling some member with Super, then it first try to invoke in super class and if it doesn't find same one then it'll try to invoke the same in subclass.
PS: correct me if i'm wrong

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