Possible Duplicate:
Why does this() and super() have to be the first statement in a constructor?
I'd like to have constructor chain in Java. For example, with the first constructor I have a string as a parameter, and call the second constructor as I create an object from the parameter string.
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) {
...
}
}
However, I got an error "Constructor call must be the first statement in a constructor" error.
I made a common code that is shared between the two constructors, but I'm not sure this is the only solution to bypass the issue.
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)
{
...
}
}
There is no intrinsic reason why Java could not be extended to allow statements that do not access this
before the constructor. However, that would add to the language complexity and obscure the code when used (particularly when you consider the call may be implicit).
Generally you want to keep constructors as simple as possible. init()
methods are a bad idea as they prevent the use of final
. It appears that the code is accessing a mutable static which is a really bad idea.
For your specific code, you can write:
public IMethodFinder(String projectName, String methodName,
int numberOfParameters) {
this(
JavaCore.create(
ResourcesPlugin.getWorkspace().getRoot().getProject(projectName)
),
methodName,
numberOfParameters
);
}
A more general hack is to call a static method within the call to the constructor:
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;
}
}
Edit March 2018: In message Records: construction and validation Oracle is suggesting this restriction be removed (but unlike C#, this
will be definitely unassigned (DU) before constructor chaining).
Historically, this() or super() must be first in a constructor. This restriction was never popular, and perceived as arbitrary. There were a number of subtle reasons, including the verification of invokespecial, that contributed to this restriction. Over the years, we've addressed these at the VM level, to the point where it becomes practical to consider lifting this restriction, not just for records, but for all constructors.
Solution 1: Your constructors should have a more well-directed flow to avoid using a common init
. Quite often one constructor will be more basic and construct a complete valid object, then the outer constructor can decorate this.
Solution 2: It is often good practice to use a static factory method, that for instance can handle the preprocessing you need here. This looks like a good use case for this pattern.
Solution 3: Instead of a common init
method just have static methods that do the isolated preprocessing for you. e.g. myField = processInputField(myField)
. Common init
methods play very poorly with final fields which is a stronger reason they are bad practice - essentially, yes, constructors should do the complete work of constructing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With