i was developing the below code....
class P {
//public P(){}
public P(int i) {
}
}
class D extends P {
public D(){ // default constructor must be defined in super class
}
}
public class agf {
public static void main(String[] args) {
}
}
Now in class p explicit parametrized constructor is defined and in class D default constructor is defined but it is still showing the compile time error ,please explain
Your parent Class P explicitly defines a constructor, due to which no-arg constructor will not be added automatically. When you write a no-arg constructor for class D without having a specific constructor call for the class P using super keyword as mentioned below,
Class D extends P {
public D() {
super(10);
}
}
you are instructing it to call the no-arg constructor of P. Since P only has constructor that you defined, it cannot call the no-arg constructor of P.
In simple terms every object of D will have part of P. But it has no idea how to initialize / construct that P part, since it has no no-arg constructor.
In the subclass, if you don't invoke a superclass constructor explicitly, there must be a default superclass constructor that the VM can invoke for you.
In the superclass, if you explicitly define a constructor, the default no-argument constructor is NOT generated by the compiler.
Therefore, in the situation you show, you defined a non-default constructor in the superclass, which prevented the compiler from generating the default no-arg constructor. Then in the subclass, you didn't explicitly invoke a constructor in the superclass. The compiler tried to generate a no-arg superclass constructor call and didn't find a suitable constructor to call.
Inside this constructor:
public D()
{
// no call to super?? implicit call to super()
}
There is an implicit call to the empty constructor of the super class (which doesn't exist in your case)
Either implement an empty constructor in the super class, or call the parameterized constructor explicitly, e.g.:
public D()
{
super(1);
}
I would suggest you read this tutorial as well.
When creating an instance of class D, the constructor of P is first called (since D is also P). The problem is that P's constructor cannot be called since a value has to be provided to it, and that's something you're not currently doing.
To fix that, the first line in D's constructor have to be super(value), while value can be a parameter sent to D's constructor, or..anything else you want (in case you want to leave D's constructor a default one).
You can go through it step-by-step in debug, it can help to clear things out.
Related
I am currently studying the concept of "class abstraction" and "extension" and have been wondering:
"If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?"
I understand the fact that extension instances the previous abstract class into the extended one and tries to call the default constructor but have been wondering why it gives out an error.
Is it because the constructor has been parametrized or simply because the empty constructor does not exist?
Does the extends keyword call something along the lines of this?
Object myClass = new AbstractClass();
And the missing parameters are the reason why it gives out an error so something along the lines of this would be correct
Object myClass = new AbstractClass(int foo,float boo);
And if that is it, does the super keyword essentially, if you'll allow me the term, "put" the parameters given in the parenthesis "inside" the constructor?
If that's not it what am I getting wrong? How does it actually work?
You should think of the extends keyword, in this context, as just saying that a class is the subclass of another class, and does nothing else. And that there are rules governing how subclasses and superclasses should work.
When you construct a subclass, you must construct its superclass first. For example, to create a Bird, you must first create an Animal. That makes sense doesn't it? To demonstrate this in code:
class Animal {
public Animal() {
System.out.println("Animal");
}
}
class Bird extends Animal {
public Bird() {
System.out.println("Bird");
}
}
Doing new Bird() will first print Animal and then Bird, because the Animal's constructor is called first, and then the Bird constructor. So actually, the Bird constructor implicitly calls the superclass' constructor. This can be written as:
public Bird() {
super();
System.out.println("Bird");
}
Now what happens if the super class does not have a parameterless constructor? Let's say the constructor of Animal now takes a String name as argument. You still need to call the superclass' constructor first, but super() won't work because super() needs a string parameter!
Therefore, the compiler gives you an error. This can be fixed by calling super() explicit with a parameter.
"If I declare a parametrized constructor inside my abstract class why
won't extension on another class work unless I declare myself the
constructor with the super keyword invoking the parameters of the
abstract class's constructor?"
Because the super class says that it MUST be constructor using that declared constructor and there is no other way around. This applies to every extending class - required constructor must be called.
The same happens with any class when you declare other constructor than default one. For example, having
public class A{
//no default no-arg ctor here
public A(String name){
....
}
}
public class B{
//default no-arg ctor will be created
}
so then
B b=new B();
A a=new A(); //// INVALID!
A a=new A("foobar"); // yeah that is it
The same applies when you are extending classes. To construct child instance, you must first "internally create parent instance" calling super.constructor. Since there is no default constructor, ANY of explicit declared superconstructors must be used.
When initializing an Object the constructor will always be called. Even if you do not define one constructor there will be a default one without any parameters. So if you define a constructor in the abstract class, you have to call that constructor with super().
If you do not define any constructors, then it will be implicitly called as the default one.
If I declare a parametrized constructor inside my abstract class why won't extension on another class work unless I declare myself the constructor with the super keyword invoking the parameters of the abstract class's constructor?
There is no default constructor available in AbstractClass since you define a parametrised constructor. If you don't define a constructor yourself, a default constructor without arguments is implicitly created. You can manually add such one now or you need to use the only available constructor (which is parametrised) with super().
Example of your code with defining constructor without arguments:
class AbstractClass {
AbstractClass() {} // added manually since not created implicitly
AbstractClass(int foo, float boo) {}
}
class RealClass extends AbstractClass {
RealClass() { } // calls super() implicitly
}
AbstractClass myClass = new RealClass();
Example of your code with calling super() with arguments:
class RealClass extends AbstractClass {
RealClass() {
super(1, 2);
}
}
class AbstractClass {
AbstractClass(int foo, float boo) {}
}
AbstractClass myClass = new RealClass();
i'm studying java as first language, so i'm a complete newbie.
I'm now studying inheritance between classes, and there's something i can't understand. I give you an example:
This is the main class:
public class Bici {
protected int misura;
protected String modello;
public Bici(int misura, String modello)
{
this.misura=misura;
this.modello=modello;
}
public void stampaCaratteristiche()
{
System.out.println("Size is: "+misura);
System.out.println("Model is: "+modello);
System.out.println();
}
}
This is the subclass:
public class Tandem extends Bici {
private int ruote;
public Tandem (int ruote)
{
super(misura, modello);
this.ruote=ruote;
}
public void stampaCaratteristicheTandem()
{
System.out.println("Le ruote del tandem sono "+ruote);
}
}
but when declaring super variables i get this error:
"Cannot refer to an instance field modello while explicitly invoking a constructor"
Why? Thank you!
you do not have default constructor in Bici class, it means in Tandem class it has to be invoked explicitly. like this :
private int ruote;
public Tandem (int ruote, int misura, String modello)
{
super(misura, modello);
this.ruote=ruote;
}
public void stampaCaratteristicheTandem()
{
System.out.println("Le ruote del tandem sono "+ruote);
}
A superclass constructor must execute before a subclass constructor. So that the state and behavior defined by the superclass may be correctly and completely initialized before a subclass constructor executes.
Java compiler assumes that the first line of every constructor is an implicit call to the default superclass constructor unless you explicitly use super() or this().
Note that Super keyword is used to explicitly invoke a superclass constructor. If you use this form, it must appear as the first statement of the constructor to ensure that the superclass constructor executes before the subclass constructor
The Java inheritance mechanism does not include constructors. In other words, constructors of a superclass are not inherited by subclasses. Subclasses can still call the constructors in the superclass using the super() contruct. In fact, a subclass constructor is required to call one of the constructors in the superclass as the very first action inside the constructor body. You may have seen Java classes where the subclass constructors did not seem to call the constructors in the superclass. Maybe the superclass did not even have a constructor. However, the subclass constructors have still called superclass constructors in those case. You just could not see it. Let me explain why:
If a class does not have any explicit constructor defined, the Java compiler inserts an implicit no-arg constructor. Thus, a class always has a constructor.
This is because you can not call an instance method before the instance is created. By the way, it is possible to call an instance method later on in the constructor.
This solve your problem:
public Tandem (int misura, String modello, int ruote){
super(misura, modello);
this.ruote=ruote;
}
I'm reading java docs and reading about Constructors I got confused about the below paragraph.
You don't have to provide any constructors for your class, but you
must be careful when doing this. The compiler automatically provides a
no-argument, default constructor for any class without constructors.
This default constructor will call the no-argument constructor of the
superclass. In this situation, the compiler will complain if the
superclass doesn't have a no-argument constructor so you must verify
that it does. If your class has no explicit superclass, then it has an
implicit superclass of Object, which does have a no-argument
constructor.
What does mean that the compiler will complain if the superclass doesn't have a no-argument constructor
Reference: Java Docs
https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Let's imagine a Base class such as
public class Base {
public Base(String s) {
}
}
Let's now create a subclass:
public class Sub extends Base {
}
That won't compile, because the above code is equivalent to
public class Sub extends Base {
// added by compiler because there is no explicitely defined constructor in Sub
public Sub() {
}
}
which is equivalent to
public class Sub extends Base {
// added by compiler because there is no explicitely defined constructor in Sub
public Sub() {
// added by compiler if there is no explicit call to super()
super();
}
}
The line super()tries to call the no-arg constructor of Base, but there is no such constructor.
The only way to have Sub compile is thus to explicitely define a constructor such as
public class Sub extends Base {
public Sub() {
super("some string");
}
}
By default every class has a no-argument constructor. If you create class A with a constructor with arguments, when class B extends A, you need to explicitly create a constructor which will call the super class constructor with arguments. Basically when you create a constructor, you lose the default call to the no-arg constructor (unless the constructor you created is still a no-arg constructor.
A constructor of the superclass and the subclass has to be called, implicitly or explicitly. Always.
If you provide a constructor for the subclass yourself, you can choose, which superclass constructor to call.
But if you don't provide a constructor for your subclass, Java creates a no-argument constructor for you. In that constructor it has to call a superclass constructor. But if there is no no-argument constructor in the superclass, Java cannot know which superclass constructor to call and which argument to use to do so.
class Superclass {
Superclass(String argument) {
//...
}
}
class Subclass extends Superclass {
// Implicit no-argument constructor, created by Java
Subclass() {
super(/* what String can Java put here? it cannot know it */);
}
}
Now, if there is a no-argument constructor of Superclass, Java can just call super(); in the default Subclass constructor.
Btw. that also happens automatically, if you define the Subclass constructor yourself and don't add an explicit call to a Superclass constructor. The Subclass constructor always calls a Supeclass constructor, be it explicitly or implicitly.
Actually I can not understand that what is the difference between a no-arg constructor and a default constructor.
import javax.swing.*;
public class Test extends JFrame {
public Test() {
super();
this.setSize(200,200);
this.setVisible(true);
}
public static void main(Sting[] arg) {
Test cFrame = new Test();
}
}
Does this invoke the default constructor of this class while creating Test object called cFrame?
The default constructor is a no-args constructor that the Java compiler inserts on your behalf; it contains a default call to super(); (not supper()) which is the default behavior. If you implement any constructor then you no longer receive a default constructor.
JLS-8.8.9. Default Constructor says (in part),
If a class contains no constructor declarations, then a default constructor with no formal parameters and no throws clause is implicitly declared.
If the class being declared is the primordial class Object, then the default constructor has an empty body. Otherwise, the default constructor simply invokes the superclass constructor with no arguments.
The default constructor is a constructor that the Java compiler adds to your code if no explicit constructor is available.
The default constructor invokes the super class constructor with no args.
If you have added your own constructor (no matter whether it's without parameters or with parameters) the compiler will not add the default constructor in this case.
What is a default constructor ?
It is a constructor that is added by the compiler if you have not defined a constructor.
If your class has a constructor already then the compiler will not add the default constructor.
So in your case you have the constructor,
public Test(){
super();
this.setSize(200,200);
this.setVisible(true);
}
So there is no default constructor now to be invoked by the JVM.
Answer is No. Reference variable cFrame will call non-arg constructor Test(), not default constructor. While Test() constructor will further find and call non-arg constructor of JFrame class(Parent) and so on
Every class must have at least one constructor. If not declared explicitly, java compiler provides a non-parameterised constructor, i.e, default constructor. This default constructor calls its parent class’s non-parameterised constructor It initializes class variables to their default values.
Eg:
Class Base {}
Class Derived extends Base {} // Default constructor of class "Derived" will automatically calls non-arg constructor of class "Base" and intialzes value to the variables
While non-arg constructor is defined by a programmer only. It can also intializes the variables. One more point to add here is that super() call is automatically added by the java compiler, if doesn’t find super() in derived class.
Eg:
Class Base {
int y;
public Base() {
}
public int getY() {
return y;
}
}
public class Derived extends Base {
private int x;
public Derived() { //super() will be automatically used
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
Derived d = new Derived();
System.out.println("Base x value => " + d.getX());
System.out.println("Base y value => " + d.getY());
Result:
Base x value => 0 // Default value to its primitive datatype(In this case: int)
Base y value => 0
The default constructor is as its name, if we do not create a constructor explicitly then the java compiler will create a default constructor. As a developer, if we create our own constructor with 0 arguments then it will be N.o argument constructor.
Answer to your question is No. Java won't provide a default constructor if you write any kind of constructor in class.
One difference between them is that the body of default constructor will always be empty whereas we can insert our own code in no-arg constructor.
It's easy to confuse the concepts of "default constructor" and "no-argument constructor" in Java. The reason is that a default constructor is a particular kind of no-argument constructor. However, not all no-argument constructors are default constructors.
If any constructor appears in the source code of a class, even an empty no-argument constructor, a default constructor is not generated and does not exist. Because Test declares a constructor, it does not have a default constructor, so Test cFrame = new Test(); does not call a default constructor.
These two classes are identical in terms of behavior (both have a no-argument constructor that does nothing), but one has a default constructor and the other does not.
class NoDefaultConstructor {
NoDefaultConstructor() {
// This is a no-argument constructor with an empty body, but is not a default constructor.
}
}
class HasDefaultConstructor {
// This class has no declared constructors, so the compiler inserts a default constructor.
}
In each case, you can create an instance with new NoDefaultConstructor() or new HasDefaultConstructor(), because both classes have no-argument constructors, but only HasDefaultConstructor's no-argument constructor is a default constructor.
Style note: If a constructor doesn't explicitly chain to another constructor with a call to super(...) or this(...), a call to super() is automatically inserted at the beginning of the constructor. You never need to write super() in a Java constructor. Doing so adds visual noise and is unnecessary.
I always thought that constructors aren't inherited, but look at this code:
class Parent {
Parent() {
System.out.println("S1");
}
}
class Child extends Parent {
Child() {
System.out.println("S2");
}
}
public class Test5 {
public static void main(String[] args) {
Child child = new Child();
}
}
//RESULT:
//S1
//S2
It shows that Child inherited constructor. Why there is S1 on result? Is there any possibility to create 2 constructors without parameters and have only Child constructor on result without base constructor (only S2)?
Whatever you are seeing here is called as constructor chaining. Now What is Constructor Chaining:
Constructor chaining occurs through the use of inheritance. A subclass
constructor method's first task is to call its superclass' constructor
method. This ensures that the creation of the subclass object starts
with the initialization of the classes above it in the inheritance
chain.
There could be any number of classes in an inheritance chain. Every
constructor method will call up the chain until the class at the top
has been reached and initialized. Then each subsequent class below is
initialized as the chain winds back down to the original subclass.
This process is called constructor chaining.(Source)
That's what happening in your program. When you compile your program , your Child is compiled to this way by javac:
class Child extends Parent
{
Child()
{
super();//automatically inserted here in .class file of Child
System.out.println("S2");
}
}
And your Parent class is converted to following:
Parent()
{
super();//Constructor of Object class
System.out.println("S1");
}
That's why your output is showing as:
S1 //output from constructor of super class Parent
S2 //output from constructor of child Class Child
Java doc says :
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.
If you don't declare a constructor of any type, a default is added.
If you don't call any other constructor in the first line of your subclass, a call to super() is made.
You write:
It shows that Child inherited constructor.
Constructors can not be inherited. Classes can be inherited, so Child does not inherit any constructor. Child inherits class Parent. Parent inherits class Object. When you call the Child constructor, automatically an Object constructor is called and then a Parent constructor, before the code of the Child constructor is run.
This why you get this result:
S1
S2
Constructor are not inherited.
Super class constructor are not inherited in derived class.
Is there any possibility to create 2 constructors without parameters and have only Child constructor on result without base constructor.
No, Its not possible In Java every derived class constructor call super class constructor. If you not add it call no argument constructor.
public SuperClass() {
...
}
public DerivedClass() {
//Compiler here call no argument constructor of Super class.
}
A constructor will always call its superclass constructor unless an explicit constructor has been defined. From 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 implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
If superclass doesn’t have default constructor, then subclass also needs to have an explicit constructor defined. Else it will throw compile time exception. In the subclass constructor, call to superclass constructor is mandatory in this case and it should be the first statement in the subclass constructor.
public class HelloWorld{
private static class A {
A(String x) {
System.out.println(x);
}
}
private static class B extends A {
}
public static void main(String []args){
B b = new B();
System.out.println("Hello World");
}
}
Output:
/*
error: constructor A in class A cannot be applied to given types;
private static class B extends A {
^
required: String
found: no arguments
reason: actual and formal argument lists differ in length
1 error
*/
So what it means is constructors are never inherited
Hence, what happens here is class B's argument less constructor tries to call class A's argument less contructor, But it didn't find that hence gives it gives error.
If we add argument less constructor in class A, then this program will work properly.