如何在Java中重写父构造函数?

如何在Java中重写父构造函数?,java,inheritance,overriding,super,Java,Inheritance,Overriding,Super,我现在有一个类,我们称之为Person,它有一个这样的构造函数 public class Person { private String name; public Person(String name) { this.name = name; System.out.println("This person is: "+getName()); } public String getName() {

我现在有一个类,我们称之为Person,它有一个这样的构造函数

public class Person
{
    private String name;

    public Person(String name)
    {
        this.name = name;
        System.out.println("This person is: "+getName());
    }

    public String getName()
    {
        return this.name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
}
然后我们用一个更具体的类型的人继承这个类,在本例中是一个雇员

public class Employee extends Person
{
    private int id;

    public Employee(String name, int id)
    {
        super(name);
        this.id = id;
        System.out.println("This person is: "+getName()+", identified by #"+getId());
    }

    public int getId()
    {
        return this.name;
    }

    public void setId(int id)
    {
        this.id = id;
    }
}
我想让Employee在创建对象时打印自己的语句,但它同时打印Person和Employee的打印语句。我如何重写此语句以避免发生这种情况?是否有更好的方式打印到控制台以防止这种情况发生

我如何重写此语句以避免发生这种情况

您不能,除非您可以编辑
Person
以提供一个不执行
System.out.println
调用的构造函数。子类必须调用它的一个超类构造函数。你的
Person
类只有一个,其中包括
System.out.println
调用,因此
Employee
别无选择,只能调用它

这是构造器不应该有副作用的几个原因之一。
Person
Employee
都不应调用
System.out.println
。这应该留给使用类或方法(而不是构造函数)的代码来完成



如果不显式执行,编译器将在构造函数的开头插入
super()
。在您的情况下,这将是一个编译错误,因为
Person
没有零参数构造函数。

当您调用
super
时,将调用父构造函数。无法避免的是:
super
就是为了这个


如果要在对象创建时调用不同的
println
s一次,则必须将
println
放在构造函数外部。一个好的选择是使用生成器或工厂模式,在
Person
Employee
类中重写
toString
,并从生成器或工厂调用
toString

因为您已经定义了自己的Person构造函数,所以该类没有可用的无参数构造函数供您使用。但是如果你把它加回去,那么你可以让一个子类有它自己的行为

 public class Person {
    protected String name;

    public Person() {} 

    public Person(String name) {
        this.name = name;
        System.out.println("This person is: "+getName());
    }
然后不需要添加超级呼叫自己

public class Employee extends Person {
    private int id;

    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
        System.out.println("This person is: "+getName()+", identified by #"+getId());
    }

您可以删除
super(name)
,但不能覆盖一行中的一行constructor@cricket_007-不,您不能删除
super(name)
@cricket\u 007-是的,它是。如果省略它,编译器将在构造函数的开头插入一个
super()
调用。OP的
Person
没有无参数构造函数,因此无法编译。@t.J所以,添加一个无参数构造函数,然后?@cricket\u 007当然,这是一个选项。这与“不需要调用超级构造函数”非常不同。(本质上,我的回答如下:提供一个不执行
System.out.println
调用的构造函数。)这是一种反模式
Person
应该负责初始化自身,而不是将其留给子类。相反(正如我在回答中所说):提供一个
Person
构造函数,它不执行
System.out.println
调用(但初始化
name
),并调用它。事实上,它不会编译<代码>名称是
私有的