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

可能重复:
为什么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的惯例? 调用常用方法是一种好方法吗?

没有内在的原因可以解释为什么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; } } 

编辑20183月:在消息记录中:构造和validation Oracle建议删除此限制(但与C#不同, this在构造函数链接之前肯定是未分配的 (DU))。

从历史上看,this()或super()必须首先在构造函数中。 这种限制从未受到欢迎,并被认为是武断的。 有许多微妙的原因,包括validation特殊参与,导致了这种限制。 多年来,我们已经在虚拟机层面解决了这些问题,以至于考虑解除这一限制变得切实可行,不仅仅是记录,而是所有构造函数。

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

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

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

对于你的第二个问题,请看第一个问题的答案 – 是的,对于这些案例,使用某种init()方法是相对容易接受的

看看这个。 它可能有助于理解java constroctor调用。

构造函数调用必须是构造函数中的第一个语句