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

Posted

技术标签:

【中文标题】Java错误:默认构造函数未定义隐式超级构造函数【英文标题】:Java error: Implicit super constructor is undefined for default constructor 【发布时间】:2010-11-14 22:05:41 【问题描述】:

我有一些简单的 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

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

【问题讨论】:

请离开“冗余”构造函数!它保持代码的可读性,并且所有现代 IDE 都可以自动创建它,因此您只需键入一个快捷方式。 一年后重新阅读我自己的问题,我突然想到我可以像 matt b 建议的那样删除构造函数(包括在基类中),然后使用静态工厂方法来构建实例。 【参考方案1】:

这是一个简单的例子

public class A 
    public A(int i)
       //
    

 

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

【讨论】:

【参考方案2】:

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

        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),调用具有匹配参数列表的超类构造函数。

【讨论】:

【参考方案3】:

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

    点击项目。 点击属性 > Java 构建路径 > 库 > JRE 系统库 > 编辑 选择默认系统 JRE 并完成 应用并关闭。

【讨论】:

明白了!完美!【参考方案4】:

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

在 Eclipse IDE 下:

    打开菜单Project --> Properties,或在Package Explorer 中右键单击您的项目并选择Properties em>(Windows 上 Alt+Enter,Mac 上 Command+I) 点击Java Build Path,然后点击Libraries标签 选择 ModulepathClasspath 并按 Add Library... 按钮 选择JRE 系统库然后点击下一步 保持Workspace default JRE被选中(你也可以选择其他选项)并点击Finish 最后按应用并关闭

【讨论】:

【参考方案5】:

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

【讨论】:

【参考方案6】:

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

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

【讨论】:

在 Eclipse 中无缘无故地收到此错误。然后我清理了工作区(菜单 Project -> Clean...),它就消失了。【参考方案7】:

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

例如: 来自:

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



收件人:

public static Hashmap<String,String> getMap()

  try

  catch(SQLException)
   
  

【讨论】:

这个答案与缺少构造函数的编译器错误无关。【参考方案8】:

如果你没有调用超类构造函数作为子类构造函数的第一条语句,Eclipse 会给出这个错误。

【讨论】:

【参考方案9】:

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

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


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

【讨论】:

【参考方案10】:

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

干杯。

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

【讨论】:

这使得构造无效对象(没有someString的对象)变得容易,因此完全违背了作为构造函数的目的。【参考方案11】:

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

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

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”,其他类就不会中断。

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

【讨论】:

是的,除非您不能再确保您的实例已正确初始化(例如,在这种特殊情况下具有名称) @ChssPly76 :是的,但这可能是因为继承使用不当。我扩展了我的答案以涵盖它。【参考方案12】:

你得到这个错误是因为一个没有构造函数的类有一个 default 构造函数,它是无参数的,相当于下面的代码:

public ACSubClass() 
    super();

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

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

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

【讨论】:

“这可能有点违反直觉,因为您可能认为子类自动具有基类具有的任何构造函数。” +1 为了后代,我会向未来的读者推荐我的解决方案:在BaseClass 中创建一个无参数构造函数,但让它简单地抛出一个UnsupportedOperationException 或其他东西。这不是最好的解决方案(它错误地暗示该类可以支持无参数构造函数),但它是我能想到的最好的。

以上是关于Java错误:默认构造函数未定义隐式超级构造函数的主要内容,如果未能解决你的问题,请参考以下文章

隐式超级构造函数 Person() 未定义。必须显式调用另一个构造函数?

java 中使用jmx对tomcat实时监控默认的构造方法无法处理的异常类型的隐式超级构造函数抛出异常

Minecraft 修改块构造器错误

C++:对象和类|| 类的构造函数与析构函数

C++:对象和类|| 类的构造函数与析构函数

构造函数constructor 与析构函数destructor