Вопрос о членах класса в Java - PullRequest
2 голосов
/ 14 января 2011

Если у меня есть класс SOmeClass с методом someMethod, в следующем коде, как компилятор читает член класса someConstant?

Class SomeClass{
            private int someConstant = someMethod(3); //3 is arbitrary

            private int anotherConstant;
            SomeClass(){
                 //constructor
                 anotherConstant = someConstant;
                     }

            public int someMethod(int an_int_value){
                 //something
                    return new_int;
                      }

Этот вопрос о моей путанице в работе компиляторов. И как машина читает код. Константа someConstant не может быть инициирована, пока не будет создан экземпляр класса, потому что компилятор должен знать, что делает метод someMethod. Но этот конструктор не может быть завершен, потому что другая переменная также должна иметь это неизвестное значение. Мне кажется (кому-то без опыта информатики), что это сложная ситуация. Этот вопрос не ограничивается Java. Это просто мой самый знакомый язык.

Ответы [ 3 ]

4 голосов
/ 14 января 2011

Создание объектов в Java - это многошаговый процесс.Во-первых, каждое поле в классе инициализируется значением по умолчанию (0, ложь или ноль в зависимости от ситуации).Затем каждое поле с инициализатором по порядку инициализируется этим значением.Если это означает вызов каких-либо методов, то эти методы вызываются с полями, которые содержат их значение по умолчанию (если они еще не были затронуты) или значение, к которому они были инициализированы.Наконец, вызывается конструктор.

Обратите внимание, что это означает, что память для объекта выделяется до запуска конструктора.Это необходимо для того, чтобы этот подход работал.

0 голосов
/ 14 января 2011

Вы, похоже, путаете компилятор со временем выполнения. То, что делает someMethod(), определяется во время компиляции и сохраняется в выходном файле .class. Среда выполнения читает эти файлы .class и строит определения классов из них. Таким образом, он обладает полным знанием того, что делает someMethod (), прежде чем вы попытаетесь создать экземпляр SomeClass. Нет ограничений на то, что конструктор должен завершить работу, прежде чем методы класса будут иметь определение.

Что Java делает, так это запускает все инициализаторы в порядке, в котором они объявлены, затем запускает то, что находится в фактическом конструкторе. Рассмотрим:

private Integer foo = getFoo();
private Integer bar = Integer.valueOf(4);
private Integer getFoo() {return bar;}

foo будет нулевым, когда мы закончим, потому что он был объявлен первым, а bar все еще был нулевым, когда мы его присвоили.

private Integer bar = Integer.valueOf(4);
private Integer foo = getFoo();
private Integer getFoo() {return bar;}

Таким образом, foo будет 4, когда строительство будет завершено! В любом случае, среда выполнения может посмотреть определение метода getFoo () до того, как конструктор будет создан, потому что компилятор поместил определение этого в файл класса.

0 голосов
/ 14 января 2011

Не будучи экспертом по Java VM, я все же постараюсь ответить на ваш вопрос:

  1. На самом деле ваша проблема не в том, что касается компилятора - компилятор только превращает ваш читаемый код Java в двоичные инструкции. Проблема наличия неинициализированных переменных возникнет во время выполнения, если только компилятор не будет достаточно умным, чтобы найти циклические зависимости в вашем коде.

  2. Ни одно из ваших значений не является константой - они должны были бы быть объявлены final, и вы бы не смогли установить anotherConstant таким образом, если бы вы объявили это таким образом. Они обе переменные.

  3. Сначала ваш класс будет загружен в память. Таким образом, будет известна базовая схема памяти SomeClass, а также функциональность someMethod(). Если бы у вас были объявлены статические переменные, они теперь также были бы инициализированы, но вы не могли бы вызвать метод экземпляра, такой как someMethod, для этого.

  4. Когда вы создаете экземпляр объекта типа SomeClass, все переменные-члены будут установлены первыми, поэтому someConstant больше не будет неизвестным. Поскольку функциональность someMethod также известна, это не должно быть проблемой. Если бы вы ссылались на необъявленную переменную в какой-то момент в someMethod, было бы выброшено NullPointerException.

  5. Наконец, вызывается конструктор. На данный момент все переменные-члены доступны, так что все будет работать гладко. Опять же - если бы были какие-то необъявленные переменные, было бы выброшено NullPointerException. В вашем примере их не должно быть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...