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)
{
...
}
}
- Why does Java require constructor call as the first statement? What's the idea behind this requirement?
- What is Java's convention for my case? Is the calling common method a good way to go?
Answer
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.
No comments:
Post a Comment