"Вызов конструктора должен быть первым оператором в конструкторе" проблема в 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) {
        ... 
    }
}

тем не менее, я получил ошибку " вызов конструктора должен быть первым оператором в ошибка конструктора.

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 ответов


нет внутренней причины, по которой 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: в записи: строительство и проверка Oracle предлагает удалить это ограничение (но в отличие от C#,this будет определенно неприсвоенным (DU) перед цепочкой конструктора).

исторически это () или super () должно быть первым в конструкторе. Этот ограничения никогда не были популярны и воспринимались как произвольные. Там были ряд тонких причин, включая проверку invokespecial, что способствовало этому ограничению. На протяжении многих лет, мы рассмотрели их на уровне VM, до точки, где он становится практично рассмотреть вопрос об отмене этого ограничения, а не только для записей, но для всех конструкторов.


Решение 1: Ваши конструкторы должны иметь более хорошо направленный поток, чтобы избежать использования общего init. Довольно часто один конструктор будет более базовым и построит полный допустимый объект, тогда внешний конструктор может украсить это.

решение 2: часто рекомендуется использовать статический заводской метод, который, например, может обрабатывать предварительную обработку, необходимую здесь. Это выглядит как хороший вариант использования для этого шаблона.

решение 3: вместо общего init метод просто имеет статические методы, которые выполняют изолированную предварительную обработку для вас. например,myField = processInputField(myField). Common init методы играют очень плохо с конечными полями, что является более сильной причиной того, что они плохая практика - по существу, да, конструкторы должны выполнять полную работу по строительству.


посмотреть ответ к вашему 1-му вопросу что касается вашего 2-го вопроса - да, его относительно принято использовать какой-то метод init() для этих случаев


взгляните на это. Это может помочь в понимании вызова Java constroctor.

вызов конструктора должен быть первым оператором в конструкторе