91

I have a some simple Java code that looks similar to this in its structure:

abstract public class BaseClass {
    String someString;
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

public class ACSubClass extends BaseClass {
    public ASubClass(String someString) {
        super(someString);
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

I will have quite a few subclasses of BaseClass, each implementing the getName() method in its own way (template method pattern).

This works well, but I don't like having the redundant constructor in the subclasses. It's more to type and it is difficult to maintain. If I were to change the method signature of the BaseClass constructor, I would have to change all the subclasses.

When I remove the constructor from the subclasses, I get this compile-time error:

Implicit super constructor BaseClass() is undefined for default constructor. Must define an explicit constructor

Is what I am trying to do possible?

Jeff Axelrod
  • 25,625
  • 29
  • 137
  • 239
Joel
  • 10,593
  • 17
  • 58
  • 72
  • 1
    Please, leave the 'redundant' constructor! It maintains readability of your code and all modern IDEs can create it automatically, so you just have to key a shortcut. – Andreas Dolk Jul 29 '09 at 06:40
  • 3
    Re-reading my own question a year later and it occurs to me that I could have removed the constructors (incl in the base class) like matt b suggested, and then use a static factory method to build instances. – Joel Aug 28 '10 at 10:43

12 Answers12

146

You get this error because a class which has no constructor has a default constructor, which is argument-less and is equivalent to the following code:

public ACSubClass() {
    super();
}

However since your BaseClass declares a constructor (and therefore doesn't have the default, no-arg constructor that the compiler would otherwise provide) this is illegal - a class that extends BaseClass can't call super(); because there is not a no-argument constructor in BaseClass.

This is probably a little counter-intuitive because you might think that a subclass automatically has any constructor that the base class has.

The simplest way around this is for the base class to not declare a constructor (and thus have the default, no-arg constructor) or have a declared no-arg constructor (either by itself or alongside any other constructors). But often this approach can't be applied - because you need whatever arguments are being passed into the constructor to construct a legit instance of the class.

matt b
  • 132,562
  • 64
  • 267
  • 334
  • 17
    "This is probably a little counter-intuitive because you might think that a subclass automatically has any constructor that the base class has." +1 – Mr_and_Mrs_D Apr 03 '13 at 15:26
  • 2
    For the sake of posterity, I'll suggest my solution for future readers: create a no-arg constructor in `BaseClass` but make it simply throw an `UnsupportedOperationException` or something. It's not the best solution (it falsely suggests that the class can support a no-arg constructor), but it's the best I can think of. – JMTyler Feb 04 '15 at 03:08
51

For those who Google for this error and arrive here: there might be another reason for receiving it. Eclipse gives this error when you have project setup - system configuration mismatch.

For example, if you import Java 1.7 project to Eclipse and you do not have 1.7 correctly set up then you will get this error. Then you can either go to Project - Preference - Java - Compiler and switch to 1.6 or earlier; or go to Window - Preferences - Java - Installed JREs and add/fix your JRE 1.7 installation.

Dean Meehan
  • 2,321
  • 17
  • 33
MF.OX
  • 2,020
  • 21
  • 24
  • 2
    Just got this error for no apparent reason in Eclipse. Then I cleaned the workspace (menu Project -> Clean...) and it went away. – erickrf Feb 24 '14 at 22:17
8

It is possible but not the way you have it.

You have to add a no-args constructor to the base class and that's it!

public abstract class A {
    private String name;
    public A(){
        this.name = getName();
    }
    public abstract String getName();


    public String toString(){
        return "simple class name: " + this.getClass().getSimpleName() + " name:\"" + this.name + "\"";
    }
}
class B extends A {
    public String getName(){
        return "my name is B";
    }
    public static void main( String [] args ) {
        System.out.println( new C() );
    }
}
class C extends A {
    public String getName() {
        return "Zee";
    }
}

When you don't add a constructor ( any ) to a class the compiler add the default no arg contructor for you.

When the defualt no arg calls to super(); and since you don't have it in the super class you get that error message.

That's about the question it self.

Now, expanding the answer:

Are you aware that creating a subclass ( behavior ) to specify different a different value ( data ) makes no sense??!!! I hope you do.

If the only thing that is changes is the "name" then a single class parametrized is enough!

So you don't need this:

MyClass a = new A("A");
MyClass b = new B("B");
MyClass c = new C("C");
MyClass d = new D("D");

or

MyClass a = new A(); // internally setting "A" "B", "C" etc.
MyClass b = new B();
MyClass c = new C();
MyClass d = new D();

When you can write this:

MyClass a = new MyClass("A");
MyClass b = new MyClass("B");
MyClass c = new MyClass("C");
MyClass d = new MyClass("D");

If I were to change the method signature of the BaseClass constructor, I would have to change all the subclasses.

Well that's why inheritance is the artifact that creates HIGH coupling, which is undesirable in OO systems. It should be avoided and perhaps replaced with composition.

Think if you really really need them as subclass. That's why you see very often interfaces used insted:

 public interface NameAware {
     public String getName();
 }



 class A implements NameAware ...
 class B implements NameAware ...
 class C ... etc. 

Here B and C could have inherited from A which would have created a very HIGH coupling among them, by using interfaces the coupling is reduced, if A decides it will no longer be "NameAware" the other classes won't broke.

Of course, if you want to reuse behavior this won't work.

OscarRyz
  • 184,433
  • 106
  • 369
  • 548
  • 2
    Yes, except you can no longer ensure that your instances are initialized properly (e.g. have names in this particular case) – ChssPly76 Jul 29 '09 at 01:38
  • @ChssPly76 : Yes, but that's probably because the inheritance is being used in a poorly way. I expanded my answer to cover it. – OscarRyz Jul 29 '09 at 01:53
4

You could also get this error when JRE is not set. If so, try adding JRE System Library to your project.

Under Eclipse IDE:

  1. open menu Project --> Properties, or right-click on your project in Package Explorer and choose Properties (Alt+Enter on Windows, Command+I on Mac)
  2. click on Java Build Path then Libraries tab
  3. choose Modulepath or Classpath and press Add Library... button
  4. select JRE System Library then click Next
  5. keep Workspace default JRE selected (you can also take another option) and click Finish
  6. finally press Apply and Close.
Emilio M.
  • 5
  • 3
2

Another way is call super() with the required argument as a first statement in derived class constructor.

public class Sup {
    public Sup(String s) { ...}
}

public class Sub extends Sup {
    public Sub() { super("hello"); .. }
}
1

I have resolved above problem as follows:

  1. Click on Project.
  2. click on properties > Java Build Path > Library > JRE System Library > Edit
  3. Select default system JRE And Finish
  4. Apply and close.
0

Eclipse will give this error if you don't have call to super class constructor as a first statement in subclass constructor.

Sagar
  • 4,474
  • 4
  • 29
  • 57
0

Sorry for necroposting but faced this problem just today. For everybody also facing with this problem - one of he possible reasons - you don't call super at the first line of method. Second, third and other lines fire this error. Call of super should be very first call in your method. In this case everything is well.

Serj.by
  • 454
  • 5
  • 16
0

Short answer: Add a constructor with no argument in base/parent/super class. i.e for example,

        class Parent{
    
    String name;
    int age;
    String occupation;
            //empty constructor
            public Parent(){
            
        }
    
    public Parent(String name, int age, String employment){
    this.name = name;
    this.age = age;
    this.occupation = employment;
    }
}

// You can have any additional constructors as you wish aka constructor overloading here in parent class.

If a super class does not have the no-argument constructor then you will get the compile-time error. Object does have such the constructor, so if Object is a only super class then there is no problem.

// then let's inherit

    class Child extends Parent{
              Child(String name, int age){
this.name = name;
this.age = age;
    }
    
    }

With super(), a super class no-argument constructor is called and with super(parameter list), a super class constructor with the matching parameter list is called.

0

Here is simple example

public class A {
    public A(int i){
       //
    }

 }

class B extends A {
    public B(int i){
      super(i);
    }
  }
Mukta
  • 777
  • 8
  • 10
-1

You can solve this error by adding an argumentless constructor to the base class (as shown below).

Cheers.

 abstract public class BaseClass {
        // ADD AN ARGUMENTLESS CONSTRUCTOR TO THE BASE CLASS
        public BaseClass(){
        }

        String someString;
        public BaseClass(String someString) {
            this.someString = someString;
        }
        abstract public String getName();
    }

public class ACSubClass extends BaseClass {
    public ASubClass(String someString) {
        super(someString);
    }
    public String getName() {
        return "name value for ASubClass";
    }
}
BrainO2
  • 1,375
  • 1
  • 8
  • 6
  • That makes it easy to construct invalid objects (ones without `someString`) set and hence totally defeats the purpose of as constructor. – Robert Aug 31 '16 at 01:03
-1

I had this error and fixed it by removing a thrown exception from beside the method to a try/catch block

For example: FROM:

public static HashMap<String, String> getMap() throws SQLException
{

}

TO:

public static Hashmap<String,String> getMap()
{
  try{

  }catch(SQLException)
  { 
  }
}
depperm
  • 8,490
  • 4
  • 37
  • 57
Thomas Johnson
  • 178
  • 1
  • 5