1

我正在为我的入门编程课程布置家庭作业。我们最近了解了构造函数以及它们的工作原理和作用,但我不明白为什么每个对象都需要一个。这似乎只是额外的工作,因为您也可以实例化对象并在它们之外运行语句。例如,在测试了编写相同代码的不同方法后,我发现

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

    }
}

为什么与第一个代码块相反,这段代码会在没有提供构造函数的情况下抛出错误?

4

2 回答 2

10

您所展示的(使用编译器提供的默认构造函数和变量初始化器)在以下情况下很好:

  • 您的初始化永远不需要抛出任何已检查的异常
  • 您只需要在初始化中为变量赋值,而不用做任何其他事情。(您可以为更复杂的代码编写初始化程序块,但如果您要这样做,您不妨将其设为构造函数。)
  • 您的构造函数不需要任何参数

以我的经验,这些都很少是真的,尤其是最后一点。当然,如果您乐于事后设置属性,则可以不用进行管理——但我个人喜欢不可变类型,它几乎总是需要构造函数参数。

所以,考虑一下如何在没有构造函数的情况下编写这个类,但保留它的所有其他特性:

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;
    }
}
于 2012-11-03T07:39:36.160 回答
4

并不是您的第一个代码不使用构造函数。确实如此。不同之处在于,它使用的是编译器提供的默认构造函数,如果您不提供任何构造函数,编译器会提供该构造函数。

构造函数用于初始化新创建对象的状态。要么你明确地给你的构造函数,要么编译器自己添加一个默认的。

实际上,your first code after compilation变成了这样:-

StickFigure man;
public MyCartoon() {
    super();
    man = new StickFigure();
}
public static void main(String[] args) {    
    new MyCartoon();
}

因此,您可以看到,第一个代码和第二个代码之间几乎没有区别。(注意super:-如果您没有自己的super或调用,编译器会在您拥有的每个构造函数中添加一个调用作为第一个语句this

上面代码中发生的情况是 - 编译器添加了一个默认构造函数,然后将您在构造函数中完成的所有实例变量初始化移动。如果你给出了多个构造函数(在这种情况下,编译器不会提供默认的构造函数),那么instance variable初始化代码会被编译器移动到每个构造函数中。

于 2012-11-03T07:38:10.027 回答