Почему я не могу ссылаться на метод экземпляра при явном вызове конструктора? - PullRequest
33 голосов
/ 10 сентября 2010

Кто-нибудь знает, почему вы можете ссылаться на метод static в первой строке конструктора, используя this() или super(), но не нестатический метод?

Рассмотрим следующую работу:

public class TestWorking{
    private A a = null;
    public TestWorking(A aParam){
       this.a = aParam;
    }

    public TestWorking(B bParam)
    {
        this(TestWorking.getAFromB(bParam));
    }

    //It works because its marked static.
    private static A getAFromB(B param){
        A a = new A();
        a.setName(param.getName());
        return a;
    }
}

И следующий нерабочий пример:

public class TestNotWorking{
    private A a = null;
    public TestNotWorking(A aParam){
       this.a = aParam;
    }

    public TestNotWorking(B bParam)
    {
        this(this.getAFromB(bParam));
    }

    //This does not work. WHY???
    private A getAFromB(B param){
        A a = new A();
        a.setName(param.getName());
        return a;
    }
}

Ответы [ 6 ]

16 голосов
/ 10 сентября 2010

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

Почему это так?Поскольку методы экземпляра могут обращаться к полям экземпляра (нестатическим), которые могут иметь разные значения в разных экземплярах, поэтому не имеет смысла вызывать такой метод для чего-то другого, кроме существующего готового экземпляра.

12 голосов
/ 10 сентября 2010

См. Спецификация языка Java 8.8.7.1 . Это утверждает, что

Явный оператор вызова конструктора в теле конструктора не может ссылаться на какие-либо переменные экземпляра, методы экземпляра или внутренние классы, объявленные в этом классе или любом суперклассе, или использовать this или super в любом выражении; в противном случае возникает ошибка времени компиляции.

Это потому, что вы не можете вызывать метод экземпляра до его создания. Кстати, позже можно вызвать метод экземпляра в конструкторе (хотя это не решение для вас).

1 голос
/ 10 сентября 2010

TestNotWorking не инициализируется в этот момент. Проблема в том, что первый конструктор (TestNotWorking (A aParam)) может вызывать super () (внутренне это всегда происходит), то есть вы вызываете метод до вызова конструктора суперкласса. Это незаконно.

1 голос
/ 10 сентября 2010

потому что когда вы вызываете this или super в конструкторе, ваш объект еще не создан. (ваш экземпляр еще не полностью инициализирован). поэтому вызов метода экземпляра не создает сцену.

1 голос
/ 10 сентября 2010

Я думаю, это потому, что конечные переменные экземпляра еще не установлены (поэтому у вас еще нет экземпляра) и метод экземпляра может получить к ним доступ.Принимая во внимание, что вся статическая инициализация была сделана до вызова конструктора.

Greetz, GHad

0 голосов
/ 10 сентября 2010

Если метод нестатический, вы должны вызвать его для объекта.

Во втором примере вам потребуется создать объект класса TestNotWorking и вызвать getAFromB для этого объекта.

Что-то вроде:

object = new TestNotWorking();
object.getAFromB(bParam);
...