Java错误:默认构造函数未定义隐式超级构造函数

时间:2009-07-29 01:28:12

标签: java inheritance dry boilerplate

我有一些简单的Java代码,在其结构中看起来与此类似:

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";
    }
}

我将有很多BaseClass的子类,每个子类都以自己的方式实现getName()方法(template method pattern)。

这很好用,但我不喜欢在子类中使用冗余构造函数。打字更多,难以维护。如果我要更改BaseClass构造函数的方法签名,我将不得不更改所有子类。

当我从子类中删除构造函数时,我得到了这个编译时错误:

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

我正在尝试做什么?

13 个答案:

答案 0 :(得分:142)

您收到此错误,因为没有构造函数的类具有默认构造函数,该构造函数是无参数且等效于以下代码:

public ACSubClass() {
    super();
}

但是,由于你的BaseClass声明了一个构造函数(因此没有编译器可能提供的默认的no-arg构造函数),这是非法的 - 扩展BaseClass的类不能调用super();,因为BaseClass中没有无参数构造函数。

这可能有点反直觉,因为您可能认为子类自动拥有基类所具有的任何构造函数。

最简单的方法是让基类不声明构造函数(因此具有默认的无参数构造函数)或具有声明的无参数构造函数(无论是单独使用还是与任何其他构造函数一起)。但是通常不能应用这种方法 - 因为你需要将任何参数传递给构造函数来构造类的合法实例。

答案 1 :(得分:46)

对于那些谷歌出现此错误并到达此处的人:可能还有其他原因可以收到此错误。当您进行项目设置 - 系统配置不匹配时,Eclipse会出现此错误。

例如,如果您将Java 1.7项目导入Eclipse并且没有正确设置1.7,那么您将收到此错误。然后,您可以转到Project - Preference - Java - Compilerswitch to 1.6 or earlier;或者转到Window - Preferences - Java - Installed JREs并添加/修复您的JRE 1.7安装。

答案 2 :(得分:7)

这是有可能的,但不是你的方式。

你必须在基类中添加一个no-args构造函数,就是这样!

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";
    }
}

如果不向类添加构造函数(any),编译器会为您添加默认的no arg构造函数。

当defualt no arg调用super()时;因为你没有超级类,所以你会得到错误信息。

这是关于自己的问题。

现在,扩大答案:

你是否意识到创建一个子类(行为)以指定不同的值(数据)是没有意义的?? !!!我希望你这样做。

如果唯一改变的是“名称”,那么参数化的单个类就足够了!

所以你不需要这个:

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

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

当你可以这样写:

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

如果我要更改BaseClass构造函数的方法签名,我将不得不更改所有子类。

这就是为什么继承是创建HIGH耦合的工件,这在OO系统中是不可取的。应该避免,也许应该用作文代替。

想想你是否真的需要它们作为子类。这就是为什么你经常看到使用insted的接口:

 public interface NameAware {
     public String getName();
 }



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

这里B和C可以继承自A,它会在它们之间创建一个非常高的耦合,通过使用接口减少耦合,如果A决定它将不再是“NameAware”,其他类将不会破坏。

当然,如果您想重用行为,这将无效。

答案 3 :(得分:1)

如果未设置JRE,您也可能会收到此错误。如果是这样,请尝试将 JRE系统库添加到您的项目中。

在Eclipse IDE下:

  1. 打开菜单项目 - &gt; 属性,或右键单击 Package Explorer 中的项目,然后选择属性(在Windows上按Alt + Enter,在Mac上按Command + I)< / LI>
  2. 点击 Java Build Path 然后 Libraries 标签
  3. 选择 Modulepath Classpath 并按添加库... 按钮
  4. 选择 JRE系统库,然后点击下一步
  5. 选择工作区默认JRE (您也可以选择其他选项)并点击完成
  6. 最后按应用并关闭

答案 4 :(得分:0)

你的BaseClass需要一个someString,所以传递一个 试试这个:

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

public class ACSubClass extends BaseClass {
    public ASubClass() {
        super("someString");  // or a meaningfull value, same as getName()?
    }
    public String getName() {
        return "name value for ASubClass";
    }
}

abstract public class BaseClass {
    String someString;
    protected BaseClass() {  // for subclasses
        this.someString = null;  // or a meaningfull value
    }
    public BaseClass(String someString) {
        this.someString = someString;
    }
    abstract public String getName();
}

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

答案 5 :(得分:0)

另一种方法是使用必需参数调用super()作为派生类构造函数中的第一个语句。

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

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

答案 6 :(得分:0)

如果您没有调用超类构造函数作为子类构造函数中的第一个语句,那么Eclipse将会出现此错误。

答案 7 :(得分:0)

对不起尸体但是今天就遇到了这个问题。对于每个也面临这个问题的人 - 他可能的原因之一 - 你不要在方法的第一行调用super。第二,第三和其他行引发此错误。超级电话应该是你方法中的第一个电话。在这种情况下,一切都很顺利。

答案 8 :(得分:0)

我已解决以下问题:

  1. 单击项目。
  2. 单击属性> Java构建路径>库> JRE系统库>编辑
  3. 选择默认系统JRE和Finish
  4. 应用并关闭。

答案 9 :(得分:0)

简答: 在基类/父类/超类中添加一个没有参数的构造函数。例如,

        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;
    }
}

// 你可以有任何额外的构造函数,如你所愿,也就是父类中的构造函数重载。

如果超类没有无参数构造函数,那么您将收到编译时错误。 Object 确实有这样的构造函数,所以如果 Object 是唯一的超类,那么没有问题。

// 那么我们继承

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

使用 super() 调用超类无参数构造函数,使用 super(参数列表) 调用具有匹配参数列表的超类构造函数。

答案 10 :(得分:0)

这是一个简单的例子

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

 }

class B extends A {
    public B(int i){
      super(i);
    }
  }

答案 11 :(得分:-1)

您可以通过向基类添加无参数构造函数来解决此错误(如下所示)。

干杯。

 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";
    }
}

答案 12 :(得分:-1)

我遇到了这个错误,并通过将方法旁边的抛出异常移到try / catch块来修复它

例如: FROM:

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

}

TO:

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

  }catch(SQLException)
  { 
  }
}