I program on netbeans ubuntu java standart project (test preparation).
when I create AccountStudent.java I get error.
Account.java
public abstract class Account {
protected double _sum;
protected String _owner;
protected static int accountCounter=0;
public Account(String owner){
this._sum=0;
this._owner=owner;
accountCounter++;
}
}
AccountStudent.java- error: cannot find symbol: constructor Account()
public class AccountStudent extends Account{
}
Fix for problem- add empty Account constructor:
Account.java
public abstract class Account {
protected double _sum;
protected String _owner;
protected static int accountCounter=0;
public Account(){
}
public Account(String owner){
this._sum=0;
this._owner=owner;
accountCounter++;
}
}
Why should i create empty constructor Account if already he exist because he inherit Object class?
Thanks
Why should i create empty constructor
Account if already he exist because he
inherit Object class?
Constructors are not inherited. If a class has no explicit constructor, hte compiler silently adds a no-argument default constructor which does nothing except call the superclass no-argument constructor. In your case, that fails for AccountStudent because Account does not have a no-argument constructor. Adding it is one way to resolve this. Another would be to add a constructor to AccountStudent that calls the existing constructor of Account, like this:
public class AccountStudent extends Account{
public AccountStudent(String owner){
super(owner);
}
}
Every class in Java must have a constructor, if you don't define one, the compiler does that for you and create a default constructor (the one with no parameters). If you create yourself a constructor then the compiler doesn't need to create one.
So even if it inherit from Object, that doesn't mean that it'll have a default constructor.
When you instantiate an AccountStudent, you will need to call the parent constructor.
By default if you don't specify yourself a parent constructor to call, it will call the default constructor.
If you want to explicitly call a parent constructor, you'll do it with super().
There are three way to avoid the error :
Call the parent constructor with a parameter you get from the child constructor :
public class AccountStudent extends Account{
public AccountStudent(String owner){
super(String owner);
}
}
Call the parent constructor with a parameter you create yourself :
public class AccountStudent extends Account{
public AccountStudent(){
super("Student");
}
}
Call the default parent constructor but you need to create one because the compiler will not create one if a non-default constructor already exists. (the solution you gave)
JLS 8.8.9 Default Constructor
If a class contains no constructor declarations, then a default constructor that takes no parameters is automatically provided.
If the class being declared is the primordial class Object, then the default constructor has an empty body.
Otherwise, the default constructor takes no parameters and simply invokes the superclass constructor with no arguments.
In this case the AccountStudent class does not have any constructor so the compiler adds a default constructor for you and also adds a call to superclass constructor. So your child class effectively looks like:
class AccountStudent extends Account{
AccountStudent() {
super();
}
}
An object of an extended class contains state variables (fields) that
are inherited from the superclass as well as state variables defined
locally within the class. To construct an object of the extended
class, you must correctly initialize both sets of state variables. The
extended class's constructor can deal with its own state but only the
superclass knows how to correctly initialize its state such that its
contract is honored. The extended class's constructors must delegate
construction of the inherited state by either implicitly or explicitly
invoking a superclass constructor.
The Java™ Programming Language, Fourth Edition
By Ken Arnold, James Gosling, David Holmes
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 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.
If constructors do not inherits in Java, why do I get compile error(Implicit super constructor A() is not visible for default constructor. Must define an explicit constructor)?
class A {
private A() {
}
}
public class B extends A {
}
UPD. I know that super() is called in implicit B constructor. But i don't get why it can't access private constructor with super(). So, if we have only private constructors, class de facto is final?
if B extends A, B must have an access to an A constructor.
Keep in mind that a constructor always call super().
So here, the implicit parameterless constructor of B can't call the A constructor.
In Java, if you create an instance of Child Class, Parent Class instance gets created implicitly.
So Child Class constructor should be visible to Child Class as it calls the constructor of Parent Class constructor using super() in the first statement itself.
So if you change the constructor of the Parent Class to private, Child Class could not access it and could not create any instance of its own, so compiler on the first hand just does not allow this at all.
But if you want to private default constructor in Parent Class, then you need to explicitly create an overloaded public constructor in the Parent Class & then in Child class constructor you need to call using super(param) the public overloaded constructor of Parent Class .
Moreover, you might think then what's the use of private constructors. private constructors is mostly used when you don't want others from any external class to call new() on your class. So in that case, we provide some getter() method to provide out class's object.In that method you can create/use existing Object of your class & return it from that method.
Eg. Calendar cal = Calendar.getInstance();. This actually forms the basis of Singleton design pattern.
The important point is to understand that the first line of any constructor is to call the super constructor. The compiler makes your code shorter by inserting super() under the covers, if you do not invoke a super constructor yourself.
Now if you make that constructor in superclass private, above mentioned concept will fail.
Your class B has a default constructor, B() - because you didn't explicitly define any other one.
That constructor implicitly calls its super constructor, A().
But you have explicitly made that one private to class A, so you have explicitly declared that no other class, including B, can have access to it.
Can work
class A {
private A() {
}
public A(int i){
}
}
public class B extends A {
private A(){
super(10);
}
}
Or remove the private A(), defaults to public A(),
unless you have another constructor
class A {
}
public class B extends A {
private A(){
super();
}
}
An instance of class B creates an instance of class A so B must invoke super(...) if A implements a non default constractor. So the constructor should be protected for B being able to call super(...)
public class B extends A {
/*
* The default constructor B means
* public () B {super();}
*/
public B() {
}
}
So you should define a constructor which is accessible by the class B
You can change the access modifier for parent Constructor
Or else you can define other Constructor in parent class which is accessible by class B and call that constructor.
I read in scjp guide as following
In fact, you can't make a new object without invoking not just the
constructor of the object's actual class type, but also the
constructor of each of its superclasses!
For example
public class Person{
}
public class Employee extends Person{
public Employee(){
}
}
I don't create a Person instance but it is legal.
Please explain for me, thank for your help.
Whenever you instantiate a subclass, it'll call your superclass' constructor first.
You can find more about this here: JSL §8.8.7
Person.java
public class Person {
public Person() {
System.out.println("Super class constructor called");
}
}
Employee.java
public class Employee extends Person {
public Employee() {
System.out.println("Sub class constructor called");
}
}
If you then instantiate your Employee:
Employee e = new Employee();
Output:
Super class constructor called
Sub class constructor called
What they actually mean is
When you are creating a subclass object, i.e. its constructor is getting called, then superclass constructor gets callued internall
This is because for the default no-argument constructor there is a default super() call to the superclass constructor.
This goes on like the class hierarchy until the Object class.
In fact, if you do not write a no-argument constructor in superclass then the subclass declaration will throw compiler error.
public class Super {
public Super(int num){
}
}
public class Sub extends Super {
}
Here, class Sub will not compile giving the error Implicit super constructor Super() is undefined for default constructor because it cannot find a no-argument constructor in super class as the default no-argument constructor i.e. provided by compiler will have an implicit call to super().
Compiler provides a default no arg constructor only if there is no other constructor defined
As we have explicitly defined Super(int num), we will have to exlicitly create no-arg constructor as follows.
public Super(){
}
First, you don't have to create a parent instance (Parent) to instantiate a child class (Employee). You must have understood wrong.
Invoking the constructor of the parent class doesn't mean to create a new parent instance object (you're not calling it with new, so no new instance is created). You are creating a child instance, and for this, you need to first invoke the parent's constructor because of inheritance. Imagine for example the parent class has private fields that must be initialized in the constructor (for example private final fields). This fields cannot be accessed from the child class, but they can be initialized from the parent class constructor. You need to initialize this fields in the child instance, and the only way is calling super().
In this case Person has a default contructor which is invoked by default, no need to explicitly call it.
But in case Person has no default constructor, you need to call it explicitly. For example:
public class Person{
private final String name;
public Person(final String name) {
this.name = name;
}
}
public class Employee extends Person {
public Employee() {
}
}
This will not compile. You need to modify Employee so it calls Person constructor explicitly. For example:
public class Employee extends Person {
public Employee(final String name) {
super(name);
}
}
Superclass' nullary constructor is implicitly called.
Its because of constructor chaining:
First statement inside a any constructor by default is super();(This is a call to super class default constructor).
I don't create a Person instance but it is legal:
thats because you have a default constructor in Person class. So Employee class constructor can actually invoke super class constructor. Person()
Bottom line, the current class in which you are declaring a constructor, all the constructor upto the base class should be accessible via super(). If not, you have to explicitly make them accessible by explicitly making a call via super with proper parameters.
You have encountered one of the oddities of java.
If you don't define any constructors, the default, or "no args", constructor is implicitly defined. It's like invisible code.
If you define any constructor, args or no args, the implicit default constructor goes away.
To further compound the mystery, the first line of any subclass constructor must be to call a constructor of the super class. If you don't explicitly call one, the no-args constructor is implicitly called.
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.