当前位置: 首页 > 知识库问答 >
问题:

“构造函数调用必须是构造函数中的第一条语句”在Java问题[副本]

薛高澹
2023-03-14

可能的重复:
为什么this()和super()必须是构造函数中的第一条语句?

我想要一个在Java的建筑链。例如,对于第一个构造函数,我有一个字符串作为参数,并在从参数字符串创建对象时调用第二个构造函数。

public class IMethodFinder {
    public IMethodFinder(String projectName, String methodName,
        int numberOfParameters) {
        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
        IJavaProject javaProject = JavaCore.create(project);
        this(javaProject, methodName, numberOfParameters);
    }

    public IMethodFinder(IJavaProject javaProject, String methodName,
        int numberOfParameters) {
        ... 
    }
}

但是,我得到了一个错误“构造函数调用必须是构造函数中的第一条语句”错误。

我制作了一个在两个构造函数之间共享的公共代码,但我不确定这是绕过这个问题的唯一解决方案。

public class IMethodFinder {
    public IMethodFinder(IJavaProject javaProject, String methodName,
            int numberOfParameters) {
        dosomething(javaProject, methodName, numberOfParameters);
    }

    public IMethodFinder(String projectName, String methodName,
            int numberOfParameters) {
        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
        IJavaProject javaProject = JavaCore.create(project);
        dosomething(javaProject, methodName, numberOfParameters);
    }

    private void dosomething(IJavaProject javaProject, String methodName,
            int numberOfParameters)
    {
       ...  
    }

}
  • 为什么Java要求构造函数调用作为第一条语句?这个要求背后的想法是什么?
  • Java对我的情况有什么惯例?调用公共方法是一个好的方法吗?

共有2个答案

百里丁雨
2023-03-14

解决方案1:您的构造函数应该有一个指导更好的流,以避免使用通用的init。通常,一个构造函数会更基本,构造一个完整的有效对象,然后外部构造函数可以修饰它。

解决方案2:使用静态工厂方法通常是一个很好的实践,例如,它可以处理您需要的预处理。这看起来是这个模式的一个很好的用例。

解决方案3:不使用普通的init方法,而是使用静态方法为您进行独立的预处理。例如myField=processInputField(myField)。常见的init方法对final字段的处理很差,这是它们是糟糕实践的一个更有力的原因--本质上,是的,构造函数应该完成构造的全部工作。

申高峰
2023-03-14

没有内在的原因为什么不能将Java扩展为允许在构造函数之前不访问this的语句。但是,这会增加语言的复杂性,并在使用时使代码变得模糊不清(特别是当您认为调用可能是隐式的时候)。

通常,您希望构造函数尽可能简单。init()方法是一个坏主意,因为它们阻止了final的使用。代码似乎正在访问一个可变的静态,这是一个非常糟糕的主意。

对于您的特定代码,您可以编写:

    public IMethodFinder(String projectName, String methodName,
        int numberOfParameters) {
        this(
            JavaCore.create(
                ResourcesPlugin.getWorkspace().getRoot().getProject(projectName)
            ),
            methodName,
            numberOfParameters
        );
    }

一种更常见的方法是在对构造函数的调用中调用一个静态方法:

public class IMethodFinder {
    public IMethodFinder(String projectName, String methodName,
        int numberOfParameters) {
        this(createProject(projectName), methodName, numberOfParameters);
    }

    public IMethodFinder(IJavaProject javaProject, String methodName,
        int numberOfParameters) {
        ... 
    }

    private static IJavaProject createProject(String projectName) {
        IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
        IJavaProject javaProject = JavaCore.create(project);
        return javaProject;
    }
}

编辑2018年3月:在message Records:construction and validation中,Oracle建议删除此限制(但与C#不同,this将在构造函数链接之前明确取消赋值(DU))。

历史上,this()或super()必须是构造函数中的第一个。这种限制从来不受欢迎,而且被认为是武断的。有许多微妙的原因,包括对invokespecial的验证,促成了这种限制。多年来,我们已经在VM级别上解决了这些问题,现在考虑取消这个限制变得切实可行了,不仅仅是对记录,而且对所有构造函数都是如此。

 类似资料:
  • 如果将移到构造函数的最后一行,我不明白为什么下面的代码会显示错误。 我已经检查了很多关于StackOverflow的答案,但我仍然不能理解这其中的原因。请帮我用一些简单的例子和解释弄清楚这个错误。

  • 问题内容: 以下代码向我返回错误信息: 我不明白。我的代码中的构造函数是第一条语句。我究竟做错了什么? 问题答案: 构造函数名称必须与类名称相同,因此请将类名称更改为或将构造函数名称更改为。 示例 (请注意,在Java中通常第一个字母是大写字母) :

  • 我有一个班在Java延伸了另一个班 我需要构造函数来运行超级ctor 这是我的基本代码: 我想从子类中调用它 我怎么做,因为我得到错误“构造函数调用必须是构造函数中的第一个语句”,但我需要构建ctor 谢谢

  • 这个Super()的替代品是什么;我代码中的语句...因为它向我显示了一个名为:构造函数调用必须是构造函数中的第一个语句的错误。

  • 问题内容: 我正在编写一个LoginRequest类的构造函数,该类扩展了一个名为JsobObjectRequest的类(来自Android的Volley框架,但这与问题完全无关) 使用此代码: 我收到错误:对super()的调用必须是构造函数主体中的第一条语句 相反,此代码可以正常编译: 但这实际上不是一回事吗?在这两种情况下,根据传递给子类构造函数的参数值,在调用超级构造函数之前都要进行一些简

  • 我正在编写一个LoginRequest类的构造函数,该类扩展了一个名为JsobObjectRequest的类(来自Android的凌空框架,但这与问题完全无关) 使用此代码: 我得到了一个错误:对super()的调用必须是构造函数体中的第一条语句 相反,这段代码编译得很好: 但事实上不是完全一样吗?在这两种情况下,在调用超级构造函数之前,都会根据传递给子类构造函数的参数值进行一些简单的计算。既然编