I have derived a class in java.
I noticed that the superclass constructor gets called before code in my derived class constructor is executed.
Is there a way to invert that order?
Example:
class Animal
{
public Animal()
{
//do stuff
}
}
class Cat extends Animal
{
int var;
public Cat(int v)
{
var = v;
super();
}
}
This is what I would like to do, but calling super() like that gives an error...
No, there is no way to invert that order. If you explicitly call a parent class constructor you are required to do it at the top of your constructor. Calling it later would allow a child class to access the parent class's data before it's been constructed.
No, you can't invert the order of constructor calls this way. A call to super() must be the first statement in a constructor. And if there is no such call, Java inserts an implicit call to super() as the first statement.
The JLS, Section 8.8.7, states:
The first statement of a constructor body may be an explicit invocation of another constructor of the same class or of the direct superclass (ยง8.8.7.1).
ConstructorBody:
{ [ExplicitConstructorInvocation] [BlockStatements] }
There isn't a way to call run the sub class constructor before superclass constructor. That's basically like trying to create the subclass even before the superclass gets created, which is impossible since the subclass relies on superclass attributes to get created.
Related
As stated in the title, pertaining specifically to Java. In pseudocode an example of this might be:
class SubClass extends SuperClass {
protected void update() {
super.update()
// do other functionality
}
}
class SuperClass {
protected void update() {
if (something) return;
}
}
If the update method is called and the superclass then returns, does the other functionality in the subclass then execute or does it return fully to where the original subclass method is called?
As a follow up question, if this is not the case, is there a way to effectively prevent any further code from running in the superclass or subclass methods?
There's nothing special about the method call from the subclass to the superclass (other than which method gets called, which the super keyword influences, obviously). The answers to your questions flow from that fact:
Does the return keyword in a superclass method return to the subclass that called the superclass method?
Yes, just like any other method call. Sometimes, the subclass needs to do work after the superclass work is done, and/or with the return value from the superclass before returning to the caller.
...is there a way to effectively prevent any further code from running in the superclass or subclass methods?
Not from the superclass method, no. You can throw an exception, but (of course) the subclass method could catch it. Which is, again, just like any other method call.
Because the type of the method is protected, access from subclasses is
possible. Also void methods do not return.
I have read in many sources and books that constructor is used to initialise the fields when an object is created. I have also read that JVM provides a default constructor if I don't mention one. What is the purpose of a constructor if it is not required to initialise the fields like the one I have mentioned below?
I also understand that a constructor without parameter is required as
it is necessary during object creation when an argument is not passed
(when programmer-defined constructors with parameters exists).
Is it necessary for JVM to provide a constructor which is actually not required?
public class test {
int a;
public test() {
//this constructor is useless
}
public static void main(String[] args)
{
test ob= new test();
System.out.println(ob.a);
//this prints 0 which means a constructor is not required in intialising `a`
}
}
A constructor like test() makes sense if the programmer defines it since there could be other constructors which takes argument.
But why is it necessary for JVM to provide one when no constructor is declared by the programmer?
I have already tested and proved that initialising a field doesn't require constructor.
Also what does the default constructor look like?
The problem is that while you know the default constructor doesn't do anything in this example, in future the constructor might do something even if you don't realise it is and you might not be able to re-compile everywhere the code is used reliably. So the safest, simplest thing to do is to always call a constructor which might change in the future and let the JIT optimise away the constructor if it doesn't actually do anything.
The byte code always calls a contructor, whether you provide one or not. When you compile code which uses the default constructor it cannot assume the constructor doesn't do anything useful as you can add something to it later to do something useful. e.g.
Say you change
public class Test {
int a;
// public Test() { //this constructor does nothing
}
to
public class Test {
int a;
final List<String> strings = new ArrayList<>();
// public Test() { //this constructor does something now.
}
or
public class ServerTest {
final List<String> strings = new ArrayList<>();
}
public class Test extends SuperTest {
int a;
// the default constructor has to call super();
}
The constructor now initialised the strings field. You can change this class without having to re-compile everywhere it is used and say, hey, my constructor now does something useful, you should call it now.
The reason the JVM adds a default constructor if you haven't provided one is down to inheritance. Say for example you have 3 classes (A, B & C) in which B extends A and C extends B. Now when you instantiate C it will call the constructor of C and also the constructors of B and A. If a constructor was missing in one or more of these classes then the instantiation would fail. So having the compiler automatically add a default constructor avoids error like this. You may not need to actually do any work in your constructor, but it's required for the JVM to instantiate the object.
The constructor(s) (both default and custom one(s)) is not only used to initialize the fields of an object but also to initialize the object itself even if it has no fields at all. Calling the constructor, JVM allocates memory for this object and creates its reference.
It is the compiler, and not JVM, who inserts a default constructor on absence.
A default constructor is needed because the constructor of the base class needs to be called from a constructor.
The default constructor looks like:
public Test() {
super();
}
Here while you are creating the object new test(),
here parenthesis states the default constructor of object test.After creating the object,if you didnot give any constructor the default constructor is constructed by jvm.so after construction of your object first call goes to your default constructor.
The default constructor is a no argument constructor called automatically by the compiler when you haven't defined any constructor. Anyway, a constructor as the one you defined, can be also called a default constructor.
It basically calls the superclass' constructor making use of the super() method.
So the default constructor called automatically would be something like:
public ClassName(){
super();
}
Java's Compiler creates a Default Constructor if no other constructor is defined for the class.
But why?
The compiler's job is to chain the Subclass's constructor to the Super Class(ultimately Object class). It's not the Compiler's work to give a default constructor to your class therefore Java is doing it for you.
To do the chaining, it first checks if there is any constructor in the class, if yes it will add super() to that constructor.
If there is no constructor idefined in the class in order for the compiler to do a proper chaining, Java adds a default constructor and a call to super() into it.
Why ?
Because every class is a subclass of an Object class (directly or indirectly), it will inherit an object class, to do so the said Object class must be fully initialised. This is done by the default constructor.
I have an abstract class and its concrete subclass, when I create an object of subclass it automatically calls the super constructor. Is the JVM internally creating an object of the abstract class?
public abstract class MyAbstractClass {
public MyAbstractClass() {
System.out.println("abstract default constructor");
}
}
public class ConcreteClass extends MyAbstractClass{
public static void main(String[] args) {
new ConcreteClass();
}
}
then how constructor exists without an object in JVM ?? (In case of abstract class)
Also constructor gets executed after object is being created then without creating the object of abstract class how the default constructor get executed ?? (This is mentioned in Java Doc)
Is it true that you can't instantiate abstract class?
Yes.
Is JVM internally create object of abstract class ?
No, but it's a common misunderstanding (and that wouldn't be an unreasonable way for it to be done; prototypical languages like JavaScript do it that way).
The JVM creates one object, which is of the class you created (in your case, ConcreteClass). There are aspects of that one object that it gets from its superclass (MyAbstractClass) and from its subclass (ConcreteClass), but there is only one object.
The object is an aggregate of all of its parts, including parts that seem to have the same name, such as a method of the superclass that is overridden by the subclass. In fact, those methods have different fully-qualified names and don't conflict with one another, which is why it's possible to call the superclass's version of an overridden method.
So if it's just one object, why do you see the call to MyAbstractClass's constructor? Before we answer that, I need to mention a couple of things the Java compiler is doing that you don't see in the source code:
It's creating a default constructor for ConcreteClass.
In that constructor, it's calling the MyAbstractClass constructor.
Just to be thorough: In the MyAbstractClass constructor, it's adding a call to the superclass's (Object) constructor, because there's no super(...) call written within the MyAbstractClass constructor.
Here's what the code looks like with the bits the Java compiler adds for you filled in:
public abstract class MyAbstractClass {
public MyAbstractClass() {
super(); // <== The Java compiler adds this call to Object's constructor (#3 in the list above)
System.out.println("abstract default constructor");
}
}
public class ConcreteClass extends MyAbstractClass{
ConcreteClass() { // <== The Java compiler adds this default constuctor (#1 in the list above)
super(); // <== Which calls the superclass's (MyAbstractClass's) constructor (#2 in the list above)
}
public static void main(String[] args) {
new ConcreteClass();
}
}
Okay, with that out of the way, lets touch on a point TheLostMind very usefully mentioned in a comment: Constructors don't create objects, they initialize them. The JVM creates the object, and then runs as many constructors (they really should be called initializers) against that one object as necessary to give each superclass a chance to initialize its part of the object.
So in that code, what happens (and you can step through this in a debugger to fully understand it) is:
The JVM creates an object
The ConcreteClass constructor is called
The first thing that constructor does is call its superclass's constructor, in this case MyAbstractClass's constructor. (Note that this is an absolute requirement: The Java compiler will not allow you to have any logic in the constructor itself prior to the superclass constructor call.)
The first thing that constructor does is call its superclass's constructor (Object's)
When the Object constructor returns, the remainder of the MyAbstractClass constructor runs
When the MyAbtractClass constructor returns, the remainder of the ConcreteClass constructor runs
The object is returned as the result of the new ConcreteClass() expression.
Note that the above would get more complicated if there were instance fields with initializers. See the JLS and JVM specs for the full details.
JVM doesn't create object of abstract class. it is calling its super constructor
JVM will create one object, an instance of the concrete class which inherits fields and methods of abstract class
I have three classes:
public class A {
public A(){
System.out.println("in A");
}
}
public class B extends A{
public B(){
System.out.println("in b");
}
}
public class C extends B{
public C(){
System.out.println("in C");
}
}
Now I am really not sure how the constructor calls work.
If I instantiate C c= new C();, in what order (and why that order) does the constructors get called.
If I instantiate the class C, then should not it just check if the class C has got any constructor or not and if it does, it shall use it?
Why does it output-> In A In B In C?
Doesn't it go up in the hierarchy only when it doesn't find the constructor in it's own class? Or the constructors of the super class are called implicitly every time?
Super constructor are called by default from the base class constructor.
The only case in which you should call a super class constructor with super, is when you need to explicitly pass a parameter to the super class constructor itself.
So the answer is yes, they are all called. The order is from the most up class in the hierarchy down to the base class, so : A, B, C.
Default constructors are always invoked, and are invoked top-down - from the topmost super-class to the lowest base-class.
Note that the super(...) call is necessary only for parameterized constructors. In your case you don't have any, so the default gets called automatically.
When a constructor is invoked, it first calls super(), so though the stack trace will show: C->B->A, actually A will be invoked first and C will be invoked last, thus the printing will show:
in A
in B
in C
super() is implicit, as the default constructors if no constructors declared.
The constructors run upwards:
C calls B, B calls A, A calls to Object that does nothing and return to A, then outputs and return the flow to B, that outputs and return to C that outputs.
Super constructor is called by default. It is executed prior to any lines of code in the derived class's constructor. So if you call new C(), A's constructor is run, then B's, then anything in C's.
Yes when you not define any constructor it will implicitly create the default construct and call it. Now when you extends any class then like class C it go with its constructor but there it didn't find to call the super class explicitly so the compiler implicitly call the super class constructor. that why when we call the super class constructor that statement always first like this way
public C(){
super();
}
if you write any statement before calling the super class constructor you getting error
Take a look at the Java language specification
"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 is implicitly assumed by the compiler to begin with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments."
http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#41652
Class A is the super class for B and class B is super class of C. That means A is at the top position among them, where B is in top for C, next to A and C is sitting bottom of B. So class A execute first and then B and then C. It's like some priority in Java for super classes.
I read somewhere that in Java "constructors are not inherited".
On the other hand, I also read that if I don't explicitly call super, Java automatically calls the super class constructor with no arguments (such a constructor must exist in this case).
Isn't automatically calling the super class constructor (with no arguments) a form of inheritance?
What does "constructors are not inherited" exactly mean?
It means that you cannot create a subclass, using a constructor of the super class-if the subclass did not also declared it. An example;
class A {
A() {}
A(String s) {}
}
class B extends A {
}
Now you cannot do this:
B b = new B("testing");
It means just because your superclass has a contructor doesn't mean the subclass will automatically get the same constructor; you have to define it manually.
The default constructor is kind of an exception and kind of isn't. It's automatically defined for you, but it's not really "inherited" because it's still part of the subclass; it's not a member of the superclass.