Java: why "this( )" is not overriden? - java

See below example:
class A {
A() { this(1); }
A(int i) { System.out.println("A" ); }
}
class B extends A {
B() {}
B(int i) { System.out.println("B" ); }
}
public class Test
{
public static void main(String[] args) {
A o = new B();
}
}
The output:
A
Q1:Seems java does not perform late binding for "this(1)". It has been decided at compile-time.Please confirm.
Q2:Java does not perform late binding on any constructors. Please confirm.
Q3:Does this mean constructors are implicitly final?

You cannot override constructors. They don't follow inheritance rules at all. They can't follow inhertitance rule because you need a simple order for constructing your object.
e.g. in your example, if you could override the A(int) constructor A() would call B(int), but B(int) implicitly calls super() which is A() and you have infinite recursion.
It is often considered bad practice for a constructor to call an overrable method. So having constructors do this automatically would be a very bad idea.
If the constructors were final, like static final methods you wouldn't be able to hide them either, but you can, so I would say they are final either.

Java does not override the constructor.
A o = new B();
It will call B() wherein it will call super().
A() will be called and here you are calling this(1) which means it will call A(1) so nothing strange .Everything is decided at compiletime when you talk about constructors.
Answers:
Q1:Seems java does not perform late binding for "this(1)". It has been decided at compile-time.Please confirm.
Yes,Only at compile time constructors are decided.
Q2:Java does not perform late binding on any constructors. Please confirm.
Since doesn't override so no late binding.
Q3:Does this mean constructors are implicitly final?
No they are not final but you cannot override them.
EDIT:
A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass. Refer Java Docs

Q1: true
Q2: that is not about the constructor, it is more about this. this always refer to a method/field present in the class or the super class, not in the children. That makes sense since the parent does not know the implementation of the child
Q3: Kind of, Constructors are special method and it does not make sense to override them since they are chained

When you create an instance of a subclass, you must invoke a constructor of the superclass.
If you don't specify a constructor, the default (no-args) constructor is called for you.
In other words, the no-args constructor in B, is actually executed as:
B() {
super();
}

When you instantiate a subclass constructor, it first invokes its superclass' default constructor before performing its own task. This is done implicitly or via super() reference.
So a call to B() will call constructor A() which will call A(1)
Similarly if you call B(2) the output will be ( It will call default constructor A() and then A(1)
A
B

'"this()" is not overridden' doesn't mean anything, and neither do any of your other questions.
All that is happening here is that the constructors for B are both implicitly calling super(), because you didn't code anything else, and super() is A(), which calls this(1).

Related

Calling Object's constructor

Why should a class call the call the Objects default constructor of the class Objects when the class already has a parametrized constructor and a unparametrized constructor?
Example
public abstract class Foo{
private int dim1;
public Foo(int dim1) {
super();
this.dim1 = dim1;
}
public Foo() {
this.dim1 = 0;
}
}
2. Why isn't the super() method called in the unparametrized constructor in the example above?
What could happen if I forget or I don't want to call the constructor in the Object class with super() ?
Does it matter if the class which calls the super() method (Unparametrized Object's class constructor) is abstract or not ?
Why should a class call the call the Objects default constructor of the class Objects when the class already has a parametrized constructor and a unparametrized constructor?
Just because of you have it, it doesn't mean it gets called automatically. You have to call it and that is where object instantiation begins.
Why isn't the super() method called in the unparametrized constructor in the example above?
It is not a method. It is just invoking the super class default constructor. Do you know , if you didn't call it, the Java compiler automatically inserts that statement while giving you byte code. So you need not write that super() in child constructors unless you want to call specific constructor .
What could happen if I forget or I don't want to call the constructor in the Object class with super() ?
Don't worry. As said above, compiler inserts it for you.
Does it matter if the class which calls the super() method (Unparametrized Object's class constructor) is abstract or not ?
Yes, abstract or not doesn't matter. It just calls the super class constructor.
1) You probably shouldn't. It is unnecessary. It is an extra line of code which doesn't do anything.
2) Because explicitly calling super() is entirely unnecessary if your object does not extend a class other than Object (as all classes do). You could remove it from the first constructor and nothing would change. The code would compile identically.
3) Nothing. You're not required to do it.
4) This makes no difference.

Calling super() with no Superclass?

What happens (if anything) when a constructor calls 'super()' without having any superclass besides Object? Like so:
public class foo implements Serializable, Comparable {
int[] startPoint;
public foo() {
super();
startPoint = {5,9};
}
}
Edit: So if this does nothing, why would anyone explicitly write that in code? Would it make any difference if I just delete that line?
It is always OK to delete the line super(); from any constructor, and there is nothing particular about the constructors of classes that extend Object. The call of the nullary superclass constructor is always implied, so whether you write it down or not, you always get the exact same semantics.
Note that this means that if you omit a call to the superclass constructor that does something big, like start database connections or the whole GUI, all this will happen whether or not you actually write super();.
super() is the first call in constructor either it is done explicitly or implicitly.
(But of course you might need to change parameters to match parent's constructor.)
Your code:
public foo()
{
startPoint = {5,9};
}
What compiler sees from the code above:
public foo()
{
super();
startPoint = {5,9};
}
So super() is invoked whether you put it explicitly in your code or not.
Since all classes derive from Object class, you are calling constructor of Object with your super() call because your class doesn't have any intermediate parents.
There is always a super class called Object, so it will invoke constructor of Object
That just calls the Object() constructor, just as if you had any other superclass with a constructor that has no parameters.
As you stated, there is a super class (Object).
The default object constructor will be called.
It calls Object's constructor, which is empty (does nothing).
super() always call to the constructor to Object class if the class doesn't extends from one class.
Class Object is the root of the class hierarchy. Every class has Object as a super class. All objects, including arrays, implement the methods of this class.
Check this link

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

Class inheritance problem in Java, constructors with and without params

I'm learning Java (2nd year IT student) and I'm having a little problem. With inheritance to be precise. Here's the code:
class Bazowa
{
public Bazowa(int i)
{
System.out.println("konstruktor bazowy 1");
}
public Bazowa(int j, int k)
{
System.out.println("konstruktor bazowy 2");
}
}
class Pochodna extends Bazowa
{
/* Pochodna()
{
System.out.println("konstruktor pochodny bez parametru");
} */
Pochodna(int i)
{
super(i);
System.out.println("konstruktor pochodny z parametrem");
}
}
So, the Pochodna class extends the Bazowa class, and my exercise is to make a superclass that has only constructors with parameters and a subclass that has both types (with and without).
When I comment the first constructor in Pochodna class, everything works fine, but I don't really know how to make it work without commenting that part. I guess that I have to somehow call the constructor from the first one, but don't have an idea how to do that.
Any help would be appreciated,
Paul
Your first constructor from Pochodna calls by default super(), a constructor which you do not have in Bazowa.
You should either call one of the base constructors with 1 or 2 params in Pochodna(), or create a constructor with no parameters in your base class.
EDIT: Since you said you are learning Java, I will add some extra explanations to my answer.
Every class must have a constructor, so when you do not declare one explicitly, the compiler does so for you, creating a default constructor with no parameters. This constructor won’t be added if YOU declare constructors explicitly.
In inheritance, the child class is a “specialization” of the parent. That means that the child class contains the attributes and behavior of the parent class and extends on them. But you do not declare the parent elements again (unless you really want to overwrite stuff). So, when you create an instance of the child, somehow the elements taken from the parent must also be initialized. For this you have the super(...) construct.
The first thing that must be in a child constructor is a call to super(...) so that the elements taken from the parent are properly initialized before the child tries to do something with them (you can also have a call to another of child’s constructor this(...) – in this case, the last child constructor in the calling chain will call super(...) ).
Because of this, the compiler will again add a default call to super() – with no parameters – for you when you do not do so yourself in the child.
In the first constructor of Pochodna, since you did not call super(i) or super(j, k) yourself, a call to super() was placed by default. But in the parent class you explicitly specified constructors, so the default was not created by the compiler. And from here the exception, you end up calling a constructor that does not exist.
Hope this makes it easier to learn Inheritance. Cheers.
You need to specify something like this:
Pochodna()
{
super(0);
}
The trick here is that since you specify a constructor for the superclass the compiler doesn't create a no-arg constructor for you. When you make your zero-arg constructor in the superclass it tries to call the no-arg constructor in the subclass and fails to find anything.
In short, calling another constructor (either in the superclass or in the same class) in your constructor is not optional. Either you specify another constructor explicitly or a call to the superclass' zero-arg constructor will get inserted.
Since the base class does not have a parameterless constructor, you will need to call a constructor explicitly using super, providing some kind of a default value.
For example:
Pochodna()
{
super(0);
System.out.println("konstruktor pochodny bez parametru");
}
Alternatively, you can create a protected parameterless constructor in the base class. It will not be directly accessible from the outside, but derived classes will be able to use it.
Other answers handle the call to the super constructor.
Note that you could also do this:
Pochodna() {
this(0);
System.out.println("konstruktor pochodny bez parametru");
}
which would call your other constructor for Pochodna. Just another option. Study the output to understand what is happening.
As the default constructor is not present in the parent, you have to call the other constructor in the child constructor:
Pochodna() {
super(10);
}

One-arg ctor A(x) implicitly invoking super() and NOT super(x)

class A{
A(int x){}
}
class B extends A{
B(int x){}
public static void main(String args[]){
B b = new B(10);
}
}
I understand this would throw an error (one-arg constructor for B, implicitly calls super(), whereby no default-arg constructor exists for A). I am curious why one-arg constructor for B, does not use super(x) to call one-arg constructor of class A. On the contrary, putting me into the hassle of explicitly writing a no-arg constructor for A, when I don't require one!
You can rewrite your B class like so:
class B extends A{
B(int x) {
super(x);
}
}
which will do what you want. It doesn't happen implicitly, since there can be lots of different constructors in A (in your example there aren't, but there could be) and it wouldn't know which one was the right one. What if you had one class that took a length and a width, which for some reason override a class that took a width and a height. You wouldn't want Java to automatically call the superclass constructor simply because the types of the arguments matched. You would want a compile error, forcing you to explicitly call a superclass constructor with the appropriate/correct arguments.
The reason you get an implicit zero-arg constructor call for super is that the compiler does know that you want the super constructed - it just wouldn't make sense otherwise - and the zero-arg constructor is a simple, natural, and generally correct choice. Asking the compiler to be any smarter about it than that is unrealistic. You can say, "hey, there's only one constructor, and it takes the same number of arguments - how hard could it be?" But it's really hard; the possibilities of what you might want in this case are wide open. So the safe policy is: if you want anything more than the no-arg constructor, the compiler requires you to call it explicitly.
All you need to do is
B(int x){ super(x); }
There's no need for a default constructor but you do need to call the one-arg constructor from A.
Seems like the compiler could help you out here but Java is verbose like that sometimes.
A no-arg constructor you always know what it does, as it doesn't depend on any externaldata; OTOH a constructor with some arguments the compalier can't be sure what they mean so it ask you (the human) to confirm which one to use.
Example given:
class A{
A(int numberOfYears){}
}
class B extends A{
B(int numberOfApples){}
public static void main(String args[]){
B b = new B(10);
}
}
I guess this shows more clearly why the compiled doesn't use that super(int) constructor by default.
As the Zen of Python tells us: Explicit is better than Implicit
So change B(int x){} to B(int x) { super(x); }
You should then explicitly call super(x) at the beginning of your function. Basically Java will add a call to super() if it does not find a call to super of any kind -- so add your own and you will be fine.
Probably because the java designers figured it would be more likely that there is a default constructor in the superclass than that there is a constructor with the same signature that you want to call. Also maybe because the rule "if you don't invoke super explicitly, it uses the default constructor" is simpler than "if you don't invoke super explicitly, it uses the constructor of the superclass with the same signature".
I am curious why one-arg constructor
for B, does not use super(x) to call
one-arg constructor of class A.
If you are asking this as a language design question ...
I guess the Java designers thought that more complicated semantic for implicit super "call"
would be harder to understand. For example, what if the type of the superclass constructor parameter was different to the parameter type in the subclass? What if there were multiple constructors in the supertype?
I personally don't think it is a burden to include an explicit super call in every constructor. Indeed, a lot of people think it is good style.
The reason is, when you define parameterised constructor in subclass, You want to OVERRIDE something from superclass. So the superclass is not called AUTOMATICALLY. You CAN however call the super(param) (in case you are just ADDING to the functionality). But that should be the first call.
However DEFAULT constructor is by its name DEFAULT. so it will ALWAYS be called (in JLS specified order) when an object is created.
As others have pointed out, in the example you give it wouldn't be a big deal to explicitly call the one-arg constructor.
What bothers me more is when I have a super class A with two subclasses, B and C, and B and C both require the same 10 constructors with a bunch of parameters. It seems to me that the whole point of inheritance is that I should be able to put those constructors in A and not have to write the same code twice, or even write 10 pass-thru functions twice.
If I can write an ordinary function in a class that is inherited by its subclasses, why can't I write a constructor?
I wonder if it's one of those problems where if I read the code for the compiler, I would find myself saying, "Ah, I see, if they had tried to do that they would have run into this and that problem, and it would have just been an ugly mess." Or maybe they were just brain-dead the day they wrote that code. I've never really heard a satisfying explanation of why this couldn't have been made to work.
The one idea that occurs to me: Suppose B extends A. A has a function x() that returns an int. B inherits this function, so B now has a function x() that returns an int. A has a constructor A that, in effect, returns an object of type A. But a constructor for B would have to return an object of type B, not A. So it isn't really inherited, it would have to be more like "extrapolated" than inherited. So it's not quite the same thing.
Still, to say that if I have class A with constructor A(int x, int y) and B extends A that the compiler could automatically generate a constructor B(int x, int y) that calls A ... that seems like it should be do-able. Sure, maybe that's not what I want to do. But then give me a way to override it, like by explicitly declaring a different construct B(int x, int y). In real life, I almost always reproduce all my constructors in sub-classes.

Categories

Resources