Java. 隐式超类构造函数Employee()未定义。必须显式调用另一个构造函数。

28

你好,我是Java的新手,在我的生产工人类中遇到了这个错误。我的生产工人构造函数明确要求调用另一个构造函数。我不知道该怎么办?

import java.util.Date;

public class Employee
{
      private String name, number;
      private Date date;

      public Employee(String name, String number, Date date)
      {
            setName(name);
            setNumber(number);
            setDate(date);
      }

      public void setName(String n)
      {
            name = n;
      }
      public void setNumber(String n)
      {
            number = n;
            // you can check the format here for correctness
      }
      public void setDate(Date d)
      {
            date = d;
      }

      public String getName()
      {
            return name;
      }
      public String getNumber()
      {
            return number;
      }
      public Date getDate()
      {
            return date;
      }
}



public class ProductionWorker extends Employee
{
      private int shift;
      private double hourlyrate;
       // error is here (Implicit super constructor Employee() is undefined. Must explicitly invoke another constructor).
      public ProductionWorker(int shift, double hourlyrate)
      {
            setShift(shift);
            setHourlyPayRate(hourlyrate);
      }

      public void setShift(int s)
      {
            shift = s;
      }
      public void setHourlyPayRate(double rate)
      {
            hourlyrate = rate;
      }

      public int getShift()
      {
            return shift;
      }
      public double getHourlyPayRate()
      {
            return hourlyrate;
      }
}

在你的员工类中加入一个默认构造函数。public Employee() {} - user489041
6个回答

31

正如您所知,任何类的构造函数都会创建一个对象。因此,构造函数应该包含其类的适当初始化代码。但是如果您有一些扩展另一个类(我们称之为“父类”)的类,则该类的构造函数不能按定义包含所有需要的初始化代码(例如,您不能定义父类的私有字段)。这就是为什么该类的构造函数必须调用其父类的构造函数。如果您不显式调用它,则会调用默认的父类构造函数(没有任何参数)。

因此,在您的情况下,您可以在父类中实现默认构造函数或直接调用该类中的任何构造函数。


默认构造函数如下:public Employee(String hourlyrate, String shift) { shift = ""; hourlyrate = ""; } - user659658
我已经这样做了,但仍然出现相同的错误。 - user659658
4
构造函数不会创建对象,它们只是对对象进行初始化。 - Joachim Sauer
@Joachim,作为JVM开发人员之一(其实是它的一个实现者),我确实知道构造函数的作用。我使用“创建”这个词只是为了简化解释(同时所有我的解释都是简化的),因为如你所见,OP对Java还是很新手。编辑:如果我的评论显得粗鲁,那么非常抱歉,这并不是我的本意。 - xappymah
@xappymah 不,缺省构造函数是Java为我们创建的隐式无参、无主体构造函数。如果您创建了一个无参构造函数,它不会成为“默认”构造函数,而只是取代它。 - PhiLho
显示剩余2条评论

9
正如其他人已经提到的那样,您需要在您的Employee类中提供一个默认构造函数public Employee(){}。发生的情况是编译器会自动为任何没有构造函数的类提供一个无参的默认构造函数。如果您的类没有显式的超类,则它具有Object的隐式超类,该超类具有一个无参构造函数。在这种情况下,您在类Employee中声明了一个构造函数,因此您必须也提供无参构造函数。
说到这里,Employee类应该像这样:

您的Employee类

import java.util.Date;

public class Employee
{
      private String name, number;
      private Date date;

      public Employee(){} // No-argument Constructor

      public Employee(String name, String number, Date date)
      {
            setName(name);
            setNumber(number);
            setDate(date);
      }

      public void setName(String n)
      {
            name = n;
      }
      public void setNumber(String n)
      {
            number = n;
            // you can check the format here for correctness
      }
      public void setDate(Date d)
      {
            date = d;
      }

      public String getName()
      {
            return name;
      }
      public String getNumber()
      {
            return number;
      }
      public Date getDate()
      {
            return date;
      }
}

这里是Java Oracle教程 - 为你的类提供构造函数 章节。仔细阅读它,你将更清楚地了解发生了什么。


3

ProductionWorker继承了Employee,因此它具备了所有员工的能力。为了实现这一点,Java会自动在每个构造函数的第一行放置一个super();调用,您可以手动放置,但通常不需要。在您的情况下,这是必要的,因为由于Employee的构造函数具有参数,无法自动放置对super();的调用。

您需要在Employee类中定义默认构造函数,或在ProductionWorker的构造函数的第一行调用super('Erkan', 21, new Date());


这与参数类型无关。需要显式调用父类构造函数,因为父类没有无参构造函数。 - Isaac Truett
其他人回答有误,你不需要拥有任何默认构造函数,如 public Employee(){};,你只需要在子类的构造函数中调用其父类的构造函数即可,例如这样:public ProductionWorker(int shift, double hourlyrate) { super(name, number, date); setShift(shift); setHourlyPayRate(hourlyrate); } - M D P

2

如果父类缺少无参构造函数,那么必须显式调用父类构造函数。你可以在父类中添加一个无参构造函数,或者在子类中显式调用父类构造函数。


1
当你的构造函数没有立即调用super时,这个问题也可能出现。
所以这样做可以解决问题:
  public Employee(String name, String number, Date date)
  {
    super(....)
  }

但这个不会:

但这不会:

  public Employee(String name, String number, Date date)
  {
    // an example of *any* code running before you call super.
    if (number < 5)
    {
       number++;
    }

    super(....)
  }

第二个例子失败的原因是Java试图隐式调用。
super(name,number,date)

作为构造函数中的第一行......所以 Java 没有看到你稍后在构造函数中调用 super。它本质上试图执行以下操作:
  public Employee(String name, String number, Date date)
  {
    super(name, number, date);

    if (number < 5)
    {
       number++;
    }

    super(....)
  }

所以解决方案非常简单... 不要在您的super调用之前放置代码;-) 如果您需要在调用super之前初始化某些内容,请在另一个构造函数中执行,然后调用旧的构造函数... 就像这个例子从这篇StackOverflow帖子中提取
public class Foo
{
    private int x;

    public Foo()
    {
        this(1);
    }

    public Foo(int x)
    {
        this.x = x;
    }
}

0
最近在我的计算机实验室遇到了这个问题。这很简单,Erkan回答得很正确。只需输入super("你的子类名称")。所以针对你的问题--> 在你的子类构造函数的第一行输入super("ProductionWorker");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接