95

我有一些简单的 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()以自己的方式实现方法(模板方法模式)。

这很好用,但我不喜欢在子类中有多余的构造函数。打字比较多,维护起来也很困难。如果要更改BaseClass构造函数的方法签名,则必须更改所有子类。

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

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

我正在尝试做的事情可能吗?

4

12 回答 12

148

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

public ACSubClass() {
    super();
}

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

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

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

于 2009-07-29T01:36:14.320 回答
51

对于那些在谷歌上搜索此错误并到达这里的人:收到它可能还有另一个原因。当您进行项目设置时,Eclipse 会出现此错误 - 系统配置不匹配。

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

于 2013-02-19T20:30:13.393 回答
8

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

您必须向基类添加一个无参数构造函数,就是这样!

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 构造函数。

当默认没有参数调用 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 构造函数的方法签名,则必须更改所有子类。

这就是为什么继承是造成高耦合的产物,这在 OO 系统中是不可取的。应该避免它,也许应该用组合来代替。

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

 public interface NameAware {
     public String getName();
 }



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

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

当然,如果你想重用行为,这是行不通的。

于 2009-07-29T01:35:36.350 回答
4

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

在 Eclipse IDE 下:

  1. 打开菜单Project --> Properties ,或在Package Explorer中右键单击您的项目并选择Properties(Windows 上的 Alt+Enter,Mac 上的 Command+I)
  2. 单击Java 构建路径,然后单击选项卡
  3. 选择ModulepathClasspath并按Add Library...按钮
  4. 选择JRE 系统库,然后单击下一步
  5. 保持选中Workspace 默认 JRE(您也可以选择其他选项)并单击Finish
  6. 最后按Apply 和 Close
于 2016-08-31T00:21:27.693 回答
2

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

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

public class Sub extends Sup {
    public Sub() { super("hello"); .. }
}
于 2014-06-08T22:51:56.663 回答
1

我已将上述问题解决如下:

  1. 单击项目。
  2. 单击属性 > Java 构建路径 > 库 > JRE 系统库 > 编辑
  3. 选择默认系统 JRE 并完成
  4. 应用并关闭。
于 2020-10-12T12:03:35.747 回答
0

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

于 2015-04-02T15:41:38.260 回答
0

很抱歉发布了 necroposting,但今天才遇到这个问题。对于同样面临这个问题的每个人 - 他可能的原因之一 - 你不要super在第一行调用方法。第二行、第三行和其他行会触发此错误。调用 super 应该是您方法中的第一个调用。在这种情况下,一切都很好。

于 2018-02-17T12:44:26.020 回答
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(parameter list),调用具有匹配参数列表的超类构造函数。

于 2021-01-23T20:06:28.490 回答
0

这是一个简单的例子

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

 }

class B extends A {
    public B(int i){
      super(i);
    }
  }
于 2021-04-20T06:55:19.000 回答
-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";
    }
}
于 2013-08-20T21:17:51.297 回答
-1

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

例如:来自:

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

}

到:

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

  }catch(SQLException)
  { 
  }
}
于 2016-07-19T18:38:57.163 回答