“构造函数调用必须是Java中构造函数中的第一个语句”问题

时间:2012-12-28 16:25:26

标签: java constructor

  

可能重复:
  Why does this() and super() have to be the first statement in a constructor?

我想在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) {
        ... 
    }
}

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

enter image description here

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

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约定是什么?调用常用方法是一种好方法吗?

4 个答案:

答案 0 :(得分:15)

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

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

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

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

更普遍的hack是在对构造函数的调用中调用静态方法:

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月:在消息Records: construction and validation中,Oracle建议删除此限制(但与C#不同,this 肯定是未分配的( DU)在构造函数链接之前。)

  

从历史上看,this()或super()必须是构造函数中的第一个。这个   限制从未流行,被认为是武断的。曾经有   一些微妙的原因,包括验证   invokespecial,这有助于这种限制。这些年来,   我们已经在VM级别解决了这些问题,直到它成为了这一点   实际考虑解除这个限制,而不仅仅是记录,   但对于所有建设者。

答案 1 :(得分:2)

解决方案1:您的构造函数应该有一个更加明确的流程,以避免使用公共init。通常一个构造函数将更基本并构造一个完整的有效对象,然后外部构造函数可以装饰它。

解决方案2:使用静态工厂方法通常是一种很好的做法,例如,可以在此处理所需的预处理。这看起来像是这种模式的一个很好的用例。

解决方案3:代替公共init方法,只需要使用静态方法为您执行隔离预处理。例如myField = processInputField(myField)。常见的init方法在最终字段中的表现非常差,这是一个更糟糕的理由 - 实际上,是的,构造函数应该完成构建的全部工作。

答案 2 :(得分:1)

请参阅this answer第1个问题 关于你的第二个问题 - 是的,对于这些情况使用某种init()方法是相对被接受的

答案 3 :(得分:0)

看看这个。它可能有助于理解java构造函数调用。

Constructor call must be the first statement in a constructor