Java 施工人员是必要的还是仅仅为了方便而使用?

Java 施工人员是必要的还是仅仅为了方便而使用?,java,constructor,Java,Constructor,我正在玩弄编程入门课程的家庭作业。我们最近了解了构造函数以及它们是如何工作和做什么的,但我不明白为什么每个对象都需要一个构造函数。这似乎只是额外的工作,因为您也可以实例化对象并在对象之外运行语句。例如,在测试了编写相同代码的不同方法后,我发现 public class MyCartoon extends Frame { StickFigure man = new StickFigure(); public static void main(String[] args) {

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

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

    }
}

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

并不是说您的第一个代码没有使用构造函数。是的。区别在于,它使用的是编译器提供的默认构造函数,如果您不提供任何构造函数,编译器会提供默认构造函数

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

实际上,编译后的第一段代码如下所示:-

StickFigure man;
public MyCartoon() {
    super();
    man = new StickFigure();
}
public static void main(String[] args) {    
    new MyCartoon();
}
所以,你可以看到,第1个和第2个代码之间几乎没有区别。注意:-若并没有自己的super或这个调用,编译器会在每个构造函数中添加一个super调用作为第一个语句

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

这并不是说您的第一个代码没有使用构造函数。是的。区别在于,它使用的是编译器提供的默认构造函数,如果您不提供任何构造函数,编译器会提供默认构造函数

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

实际上,编译后的第一段代码如下所示:-

StickFigure man;
public MyCartoon() {
    super();
    man = new StickFigure();
}
public static void main(String[] args) {    
    new MyCartoon();
}
所以,你可以看到,第1个和第2个代码之间几乎没有区别。注意:-若并没有自己的super或这个调用,编译器会在每个构造函数中添加一个super调用作为第一个语句

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

您所展示的和变量初始值设定项的用法是正确的,如果:

您的初始化不需要抛出任何已检查的异常 您只需要在初始化过程中为变量赋值,而无需执行任何其他操作。您可以为更复杂的代码编写初始值设定项块,但如果要这样做,还不如将其设置为构造函数。 构造函数不需要任何参数 根据我的经验,这些相对来说很少都是真的,尤其是最后一点。当然,如果您愿意在以后设置属性,您可以不用设置属性就可以进行管理,但就我个人而言,我喜欢不可变类型,它几乎总是需要构造函数参数

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

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

您已经展示了和变量初始值设定项的用法,如果:

您的初始化不需要抛出任何已检查的异常 您只需要在初始化过程中为变量赋值,而无需执行任何其他操作。您可以为更复杂的代码编写初始值设定项块,但如果要这样做,还不如将其设置为构造函数。 构造函数不需要任何参数 根据我的经验,这些相对来说很少都是真的,尤其是最后一点。当然,如果您愿意在以后设置属性,您可以不用设置属性就可以进行管理,但就我个人而言,我喜欢不可变类型,它几乎总是需要构造函数参数

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

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

谢谢这解释了很多。然而,你的第一颗子弹让我有些困惑。我编写了更多的代码,并在等待答案时尝试了包含构造函数/无构造函数测试。新代码不需要抛出任何异常或任何其他项目符号,但如果我采用o
ut表示构造函数的语法。我将立即在编辑中包含该代码。@refusetocompile:是的,我的示例不包含任何异常-但请将FileInputStream作为一个包含异常的示例。您能否根据我编辑的新代码进行澄清?为什么除了构造器中的所有语句外,这段代码会抛出这么多错误?@RefuetoCompile:你没有展示不可编译的代码,只有可编译的代码-但我猜你只是在类声明中包含了语句而不是声明,这是不允许的。啊,我想我明白了。为了清楚起见,我不能像这样做:class myClass{myobjecttest=newmyobject;test.setSomething;}谢谢!这解释了很多。然而,你的第一颗子弹让我有些困惑。我编写了更多的代码,并在等待答案时尝试了包含构造函数/无构造函数测试。新代码不需要抛出任何异常或任何其他项目符号,但如果去掉表示构造函数的语法,它就会失败。我将立即在编辑中包含该代码。@refusetocompile:是的,我的示例不包含任何异常-但请将FileInputStream作为一个包含异常的示例。您能否根据我编辑的新代码进行澄清?为什么除了构造器中的所有语句外,这段代码会抛出这么多错误?@RefuetoCompile:你没有展示不可编译的代码,只有可编译的代码-但我猜你只是在类声明中包含了语句而不是声明,这是不允许的。啊,我想我明白了。为了清楚起见,我不能这样做:class myClass{myobjecttest=newmyobject;test.setSomething;}很好的解释。简短而准确。谢谢很好的解释。简短而准确。谢谢