Cannot access Grandparent class constructor - java

I've create 3 classes just look like this:
public class A{
protected int x;
public A(){
this.x=0;
}
public A(int x){
this.x=x;
}
public void doSomething(){
x=1;
}
}
public class B extends A{
#Override
public void doSomething(){
x=2;
}
}
public class C extends B{
protected int y;
public C(){
super();
y=0;
}
public C(int x, int y){
super(x);//Error
this.y=y;
}
#Override
public void doSomething(){
x=3;
y=3;
}
}
My IDE(Android studio) returned this error:
Error:(26, 8) Gradle: error: constructor B in class B cannot be
applied to given types; required: no arguments found: int reason:
actual and formal argument lists differ in length
I'm so sorry if this question came from my ignorance of OOP, but I'm really obstructed and honestly need help from you guy, please. Thank you very much!

Constructors are not inherited by subclasses. This means that B does not inherit A's two constructors. Whenever you don't create any explicit constructor, the Java compiler creates an implicit default constructor that takes no parameters and does nothing besides implicitly call the superclass constructor.
The default constructor in B is why the first constructor in C works. It explicitly calls it with super(). But because there is no B constructor that takes an int, the call to super(x) in C is an error.
When you create the explicit constructor B(int), that will get the call to super(x) to compile in C's second constructor. Because you will now have an explicit constructor, there won't be an implicit default constructor any more, so you will also have to create an explicit no-arg constructor in B so that the call to super in C's first constructor will still compile.

At the place of the error a one argument constructor of B is called. However, B does not have a one argument constructor. It has only the zero argument default constructor.
You need to add a zero argument and a one argument constructor to the class B.

Related

Use of super keyword in Java

I have doubt regarding printing of superclass constructor statement even when I have not used super() keyword in subclass.
class A
{
int i;
A()
{
System.out.println("A's constructor");
}
}
class B extends A
{
int i;
B(int a , int b)
{
super.i=a;
i=b;
}
void show()
{
System.out.println(super.i);
System.out.println(i);
}
}
class UseSuper
{
public static void main(String[] args)
{
B b=new B(1,2);
b.show();
}
}
The output of my program is:
A's constructor
1
2
I am unable to understand why I am getting A's constructor printed on my console?
Check the following lines from https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
If a subclass constructor invokes a constructor of its superclass,
either explicitly or implicitly, you might think that there will be a
whole chain of constructors called, all the way back to the
constructor of Object. In fact, this is the case. It is called
constructor chaining, and you need to be aware of it when there is a
long line of class descent.
I hope, it clears your doubts.
[Update]
Posting this update to clear OP's doubts he has mentioned in his comment below.
The following code won't compile because implicit super constructor A() has not been defined and we have also not defined it explicitly. Note that the implicit super constructor A() is automatically defined when there is no other constructor with arguments have been defined.
class A {
int i;
A(int x,int y){
}
}
class B extends A {
int i;
B(int a, int b) {
super.i = a;
i = b;
}
void show() {
System.out.println(super.i);
System.out.println(i);
}
}
public class UseSuper {
public static void main(String[] args) {
B b = new B(1, 2);
b.show();
}
}
[Another Update]
Posting this update to clear OP's another doubt which he has mentioned in his comment below.
The following code too won't compile because the super constructor A() has been declared as private preventing the child class constructor to call it.
class A {
int i;
private A() {
System.out.println("A's constructor");
}
}
class B extends A {
int i;
B(int a, int b) {
super.i = a;
i = b;
}
void show() {
System.out.println(super.i);
System.out.println(i);
}
}
class UseSuper {
public static void main(String[] args) {
B b = new B(1, 2);
b.show();
}
}
When a class extends another class, it is crucial to first call the constructor of the parent class and initialize it, before calling the constructor of the current class.
Even when not visually calling super() in any part of your constructor, Java itself calls the constructor of class A.
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the superclass does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
In other words, constructor B(int a , int b) calls constructor A() implicitly. In IDE, just change A() to A(int i) and you'll see an error message for constructor B(int a , int b) like "Implicit super constructor A() is undefined. Must explicitly invoke another constructor".

Below is the code snippet and error message, why compiler is asking for this default constructor?

class X{
X(){
System.out.println("Inside X()");
}
X(int x){
System.out.println("Inside X(int)");
}
}
class Y extends X{
Y(String s){
System.out.println("Inside Y(String)");
}
Y(int y){
super(1000);
System.out.println("Inside Y(int)");
}
}
class Z extends Y{
Z(){
System.out.println("Inside Z()");
}
Z(int z){
super(100);
System.out.println("Inside Z(int)");
}
}
public class Program{
public static void main(String args[]){
Z z=new Z(10);
}
}
The above code gives below error when compiled :-
Program.java:23: error: no suitable constructor found for Y(no arguments)
Z(){
^
constructor Y.Y(String) is not applicable
(actual and formal argument lists differ in length)
constructor Y.Y(int) is not applicable
(actual and formal argument lists differ in length)
1 error
What is the use of default constructor when we are calling parameterized constructor, java compiler is giving error i am unable to understand why this default constructor is required?
You need to specify the constructor to be used to create the super class if it has no constructor without arguments (default one) *
First statement in your constructors is a call to super() unless you indicate an explicit call to this or super with any arguments. That super() call is injected by java on compilación time. Therefore it is looking for non-args constructor at Y class.
Please refer to documentation:
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
In practice, compiler will pre-process your code and produce something like:
class X{
X(){
super(); // Injected by compiler
System.out.println("Inside X()");
}
X(int x){
super(); // Injected by compiler
System.out.println("Inside X(int)");
}
}
class Y extends X{
Y(String s){
super(); // Injected by compiler
System.out.println("Inside Y(String)");
}
Y(int y){
super(1000);
System.out.println("Inside Y(int)");
}
}
class Z extends Y{
Z(){
super(); // Injected by compiler
System.out.println("Inside Z()");
}
Z(int z){
super(100);
System.out.println("Inside Z(int)");
}
}
public class Program{
public static void main(String args[]){
Z z=new Z(10);
}
}
Then It will proceed to compile it, however as you see, Z non-argument constructor try to reference Y non-argument constructor, which does not exist.
*As Carlos Heuberger clarify.

error while creating the Parent object inside child class

I have two class :-
import java.lang.*;
class A {
public A(int number) {
System.out.println("HI I AM INSIDE PARENT CONSTRUCTOR");
}
}
class B extends A {
public static void main(String[] args) {
A obj = new A(10);
}
}
Error:- Implicit super constructor A() is undefined for default constructor. Must define an explicit constructor.
The problem is that you have no constructor declared in B, so the compiler is supplying the default constructor, which in effect looks like this:
B() {
super();
}
Since A has no constructor accepting zero parameters, B can't be compiled. You'll need to add a constructor to B that calls super(int), or you'll need to add a zero-parameters constructor to A.
Principle
A subclass constructor has to invoke the parent constructor.
By default, a no arg constructor is generated by the compiler if you don't declare one.
Important detail : this generated constructor invokes the parent constructor with a no arg invocation.
Your case
You don't declare a constructor in B.
So a default no arg constructor of B is generated :
This constructor is :
B(){
super();
}
but it cannot invoke the parent constructor as it declares one parameter :
public A(int number)
So the compiler emits this error :
Implicit super constructor A() is undefined for default constructor.
Must define an explicit constructor.
To solve your problem, declare a constructor in the subclass that invokes explicitly the parent constructor with the expected argument :
public B(int number) {
super(number);
}
I think you're missing the default constructor in your A class.
See this answer for further explanation.
You have given your own constructor for A having arguments of int. now you need to add a constructor on your own to the class B as well.
public B(int number) {
super(number);
}
When you don't define a constructor in Java, you get an implicit default constructor. When you define a constructor, then the default constructor is not there anymore. So, when you have something like:
Class A {
}
this is equivalent to:
Class A {
A() {
super();
}
}
In your case, class B is calling the default constructor of A, but because A already defined another constructor, the default constructor is then not there anymore, unless you define it explicitly.
Add constructor B(int):
import java.lang.*;
class A {
public A(int number) {
System.out.println("HI I AM INSIDE PARENT CONSTRUCTOR");
}
}
class B extends A {
public B(int number) {
super(number);
}
public static void main(String[] args) {
A obj = new A(10);
}
}
Add:
public B(int number) {
super(number);
}
Cause you have defined a constructor with arguments in parent class,so the compiler won't call the default constructor without arguments.In order to instance parent class before subclass initializing,you have to call parent's explicit constructor in subclass.

Constructor of a derived class (Java)

I'm very new in Java, and about to ask a fundamental question. Hope you guys could help me. Supposed I have a base classe Super and a derived class Sub, which inheritances from class Super as follows:
public class TestSuperSub {
public static void main(String[] args) {
Super ou = new Sub(5,10);
}
}
class Super {
Super() {
System.out.println("Super()");
}
Super(int x, int y) {
System.out.println("Super(int, int)");
}
}
class Sub extends Super {
public Sub(int x, int y) {
System.out.println("Sub(int, int)");
}
}
The output is
Super()
Sub(int, int)
I understand, that ou calls Sub::Sub(int,int) and therefore, Sub(int, int) is printed. But why is Super() printed, since Super::Super() hasn't never been called?
Could someone please explain it to me.
Thanks a lot!
Cheers
By default, Java will call the no-arg constructor of a super class unless you explicitly call another constructor. If you want to call Super(int, int), you must call it explicitly:
public Sub(int x, int y) {
super(x, y);
System.out.println("Sub(int, int)");
}
But why is Super() printed, since Super::Super() hasn't never been called?
It has, because your Sub constructor is implicitly calling it. It's as if you'd written:
public Sub(int x, int y) {
super();
System.out.println("Sub(int, int)");
}
From section 8.8.7 of the JLS:
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).
...
It is a compile-time error for a constructor to directly or indirectly invoke itself through a series of one or more explicit constructor invocations involving this.
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.
If you want to call a different superclass constructor, you need to do that implicitly. When you call a subclass constructor, that will always work its way up through the inheritance hierarchy, executing the body of the superclass constructor before the subclass constructor... indeed, even field initializers in the subclass are only run after the superclass constructor.
Its the very basic fundamental concept in Java. Its the magic of super keyword and constructor chaining.
Go through these links. Hope this would help you understand the concept.
http://docstore.mik.ua/orelly/java-ent/jnut/ch03_04.htm
http://docs.oracle.com/javase/tutorial/java/IandI/super.html
By Default in constructor of sub class
the first line is call base class default constructor (implicitly) if no constructor is mentioned that is **
super();
**
if you write
super(x,y);
then other constructor will be called
Note : First line of constructor is to call base class constructor.
if there is no super class then Object class's constructor is called
When you instantiate a class, all the superclass hierarchy must also be instantiated and it will be done so through the null constructors automatically available for each class.
The following code
public class Superclassing {
public static void main(String[] args) {
new C();
}
Superclassing() { System.out.println("super"); }
}
class A extends Superclassing {
A() { System.out.println("A"); }
}
class B extends A {
B() { System.out.println("B"); }
}
class C extends B {
C() { System.out.println("C"); }
}
outputs
super
A
B
C
It is done so by design as mentioned in Skeet's answer and also here (oddly, it is mentioned before it is explained in 8.8.7):
JLS 8.8.3. Constructor Modifiers
The lack of native constructors is an arbitrary language design choice
that makes it easy for an implementation of the Java Virtual Machine
to verify that superclass constructors are always properly invoked
during object creation.
(emphasis mine.)
class A{
A(){
System.out.println("no-arg constructor in A");
}
A(int a){
System.out.println("parameterized constructor in A");
}
}
class B extends A{
B(){
System.out.println("no-arg constructor in B");
}
B(int b){
//by default during compilation super() keyword will be added in first line of this constructor
System.out.println("paramterized constructor in B");
}
}
public class TestDemo {
public static void main(String[] args) {
B aVar = new B(10);
aVar = new B();
}
}
Output:
// output for first object i.e, new B(10)
no-arg constructor in A
paramterized constructor in B
//output for second object i.e, new B()
no-arg constructor in A
no-arg constructor in B
A super() keyword will be add by default by the compiler during compilation depending on the Object that u create in main method.

constructors in java

public class A {
public A() {
System.out.println("a1");
}
public A(int x) {
System.out.println("a2");
}}
public class B extends A {
public B() {
super(5);
System.out.println("b1");
}
public B(int x) {
this();
System.out.println("b2");
}
public B(int x, int y) {
super(x);
System.out.println("b3");
}}
I don't understand why the default constructure of A is not applied when I run B b= new B();
B extends A, so First we call the constrcture of A that supposed to print "a1", and then we call the the second constructure of A which prints "a2" and B() prints "b1", but when I run it, it prints only "a2,b1", so obviously A() wan't applied at the beginning- why?
When you say B b = new B(); you are calling the default constructor which is
public B() {
super(5);
System.out.println("b1");
}
Since this already has a call to its super constructor [super(5)] so the compiler will not insert the implicit default constructor. Hence the result.
NOTE: From your question, it seems that you have the idea that all the constructors are called when you create an object. I am afraid that is incorrect. Only that constructor will be called which you explicitly call to create the object. And if that constructor calls other constructor via the this() method, only then the other constructors will be called.
B extends A, so First we call the constrcture of A that supposed to print "a1"
This statement is incorrect.
In class B your no arguments constructor
public B() {
super(5);
System.out.println("b1");
}
calls the constructor of the superclass (class A) which takes an int parameter.
public A(int x) {
System.out.println("a2");
}
You never make a call to super() so the constructor that prints "a1" will not be called when you call any of B's constructors
Calling a super constructor must be the first line of a constructor. If you wish to call the no argument constructor of a superclass (in this case, the one that prints "a1"), you would write...
public B() {
super();
System.out.println("b1");
}
If you do not specify calling a super constructor, then java will automatically put in a call to the no argument super constructor.
That's because you call super(5) in B constructor which call the second A constructor instead of the first one.
I think you missunderstand how Java handles constructors. First of all, by default Java will call only one constructor per class, unless you explicitly tell it to call more using this(...). Secondly, that one construct that is called is the default constructor of the super class (so it will call super(), not this()); so class A actually looks like this:
public class A {
public A() {
super(); // implicit call to super(), which is Object()
System.out.println("a1");
}
public A(int x) {
super(); // implicit call to super(), which is Object()
System.out.println("a2");
}
}
So invoking A() will implicitly call Object(), however invoking A(int x) will also implicitly call Object(), and not - how you seem to assume - A().
Since in B you always explicitly specify to call another constructor, the compiler will not add anything. Below I added comments on what will happen on the calls to super(...) and this(...)
public class B extends A {
public B() {
super(5); // explicit call to A(5), no implict call to A()
System.out.println("b1");
}
public B(int x) {
this(); // explicit call to B(), no implicit call to A()
System.out.println("b2");
}
public B(int x, int y) {
super(x); // explict call to A(x), no implicit call to A()
System.out.println("b3");
}
}
So again, the important thing to remember is that Java will insert a call to super() in the first line of any constructor, unless you explicitly invoke another constructor using this(...) or super(...). It will never insert this() by itself.

Categories

Resources