我正在为我的入门编程课程做家庭作业。我们最近了解了构造函数及其工作原理和工作方式,但我不明白为什么每个对象都需要一个。它似乎只是额外的工作,因为你可以实例化对象并在它们之外运行语句。例如,在测试了编写相同代码的不同方法之后,我发现了
public class MyCartoon extends Frame {
StickFigure man = new StickFigure();
public static void main(String[] args) {
new MyCartoon();
}
}
产生与此完全相同的效果:
public class MyCartoon extends Frame {
StickFigure man;
public MyCartoon() {
man = new StickFigure();
}
public static void main(String[] args) {
new MyCartoon();
}
}
我可以澄清一下吗?
但是,当我在上面的代码实例化的另一个类中尝试使用类似的代码时,在尝试编译时会抛出100多个错误。以下代码运行正常。除了StickFigure()
构造函数中的代码之外,相同的代码不会:
import wheels.users.*;
import java.awt.Color;
public class StickFigure {
Ellipse head;
Line torso;
Line leftBackArm;
Line leftForeArm;
Line rightBackArm;
Line rightForeArm;
Line leftUpperLeg;
Line leftLowerLeg;
Line rightUpperLeg;
Line rightLowerLeg;
StickFigure() {
head = new Ellipse();
head.setColor(Color.WHITE);
head.setFrameThickness(4);
head.setFrameColor(Color.BLACK);
head.setSize(80, 80);
head.setLocation(140, 130);
torso = new Line(180, 210, 160, 340);
torso.setColor(Color.BLACK);
torso.setThickness(4);
leftBackArm = new Line(180, 210, 145, 280);
leftBackArm.setColor(Color.BLACK);
leftBackArm.setThickness(4);
leftForeArm = new Line(145, 280, 132, 340);
leftForeArm.setColor(Color.BLACK);
leftForeArm.setThickness(4);
rightBackArm = new Line(180, 210, 190, 290);
rightBackArm.setColor(Color.BLACK);
rightBackArm.setThickness(4);
rightForeArm = new Line(190, 290, 225, 350);
rightForeArm.setColor(Color.BLACK);
rightForeArm.setThickness(4);
leftUpperLeg = new Line(160, 340, 140, 420);
leftUpperLeg.setColor(Color.BLACK);
leftUpperLeg.setThickness(4);
leftLowerLeg = new Line(140, 420, 105, 490);
leftLowerLeg.setColor(Color.BLACK);
leftLowerLeg.setThickness(4);
rightUpperLeg = new Line(160, 340, 180, 420);
rightUpperLeg.setColor(Color.BLACK);
rightUpperLeg.setThickness(4);
rightLowerLeg = new Line(180, 420, 180, 500);
rightLowerLeg.setColor(Color.BLACK);
rightLowerLeg.setThickness(4);
}
}
为什么这个代码与第一个代码块相反,在没有提供构造函数的情况下抛出错误?
答案 0 :(得分:10)
如果出现以下内容(使用compiler-provided default constructor和变量初始值设定项),则可以使用以下内容:
根据我的经验,这些相对很少都是真的,特别是最后一点。当然,如果你以后很乐意设置属性,你可以不用管理 - 但我个人喜欢不可变类型,几乎总是需要构造函数参数。
因此,请考虑如何在没有构造函数的情况下编写此类,但保留其所有其他功能:
public class Person {
private final String name;
private final LocalDate dateOfBirth;
public Person(String name, LocalDate dateOfBirth) {
this.name = name;
this.dateOfBirth = dateOfBirth;
}
public String getName() {
return name;
}
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
}
答案 1 :(得分:4)
这不是你的第一个代码没有使用构造函数。确实如此。区别在于,它使用编译器提供的默认构造函数,如果您不提供任何编译器,则编译器提供该构造函数。
构造函数用于初始化新创建的对象的状态。要么显式给出构造函数,要么编译器自己添加默认构造函数。
实际上,your first code after compilation
变成这样: -
StickFigure man;
public MyCartoon() {
super();
man = new StickFigure();
}
public static void main(String[] args) {
new MyCartoon();
}
所以,你可以看到,第1代和第2代之间几乎没有任何区别。 (注意: - 如果您没有自己的super
或super
,编译器会在您拥有的每个构造函数中添加this
次调用作为第一个语句调用)
上面的代码中发生了什么 - 编译器添加了一个默认构造函数,然后在构造函数中移动你在那里完成的所有实例变量初始化。
如果您已经给出了多个构造函数(在这种情况下,编译器将不提供默认构造函数),那么编译器会将instance variable
初始化代码移动到每个构造函数中。