2015-07-15 5 views
8
public class A { 
    public static String HOST; 

    static { 
    HOST = ...; 
    } 
} 

public class B { 
    public static String URL; 

    static{ 
     URL = A.HOST + ...; 
    } 
} 

Вопрос в том, должен ли A.HOST правильно инициализироваться до того, как B его использует? Это поведение определено в спецификации?Статический блок Java относится к статической переменной в другом классе

+0

Просто запустите простой тест, чтобы узнать, будет ли он инициализирован или нет – nafas

+0

, если вы сделаете ссылку на A в первую очередь, A будет полностью инициализирована, и всякий раз, когда вы вызываете B в первый раз, он будет работать нормально. Если вы сначала вызовете B, он будет каскадироваться до A, когда встретит A.HOST. – njzk2

+0

Прикольная часть была бы, если бы у A было что-то вроде 'HOST = B.FOO'. Не уверен, что он даже скомпилировался. – njzk2

ответ

7

Да что поведение корректно определено here.

Короче говоря, со ссылкой на эту ссылку из

инициализации класса или интерфейса состоит из выполнения класса или инициализации интерфейса метод <clinit>

...

Класс или интерфейс могут быть инициализированы только в результате:

Выполнение любой из инструкций виртуальной машины Java new, getstatic, putstatic или invokestatic, которая ссылается на класс или интерфейс (§new, §getstatic, §putstatic, §invokestatic). Все эти инструкции ссылаются на класс прямо или косвенно через ссылку на поле или ссылку на метод.

После выполнения новой инструкции ссылочный класс или интерфейс инициализируются, если он еще не был инициализирован.

После выполнения инструкции getstatic, putstatic или invokestatic класс или интерфейс, объявивший разрешенное поле или метод, инициализируется, если он еще не был инициализирован.

Первый вызов экземпляра java.lang.invoke.MethodHandle, который был результатом разрешения дескриптора метода виртуальной машины Java (§5.4.3.5) и имеет вид 2 (REF_getStatic), 4 (REF_putStatic) или 6 (REF_invokeStatic).

Вызов некоторых отражающих методов в библиотеке классов (§2.12), например, в классе Class или в пакете java.lang.reflect.

Инициализация одного из его подклассов.

Его обозначение как начальный класс при запуске виртуальной машины Java (§5.2).

<clinit> является метод (созданный компилятором), который инициализирует статические переменные и имеет код, который вы положили в static блоке

В вашем случае, когда static блок класса B прогонов (что будет <clinit>), он будет иметь код операции getStatic, запросив A.HOST. Таким образом инициализация A будет запущена, и A.HOST будет инициализирован. Таким образом, вы будете читать правильное значение.

+0

И ваше заключение - да или нет, A будет инициализирован до того, как B его использует? – John

+0

@ user3360241 Только что отредактировал, дайте мне знать, если все еще не ясно. – xp500

+0

теперь ясно :) – John

0

Статический блок для класса запускается на выполнение, когда class is accessed, либо создать экземпляр, или получить доступ к статическому методу или поле.

Это зависит от кода, который мы выполняем.

В вашем случае, когда мы делаем A.HOST, он также вызывает статический блок class A.

См this

0

Статический инициализатор для класса получает выполняется, когда класс первого доступа, либо создать экземпляр, или получить доступ к статическому методу или поле.

Источник: In what order do static initializer blocks in Java run?

-1

Статический блок будет выполнен, прежде чем будет выполнен метод main().

+0

Не могли бы вы объяснить, как ваш ответ связан с вопросом? – Blip

+0

Я имею в виду, что код в статическом блоке выполняется до основного метода, класс B записывается рядом с классом A, возможно, строка инициализируется, и не было бы проблем, когда к нему обращался класс B. – Gopinath

+0

Я думаю, вы не поняли вопрос , 'B.URL' и' A.HOST' являются статическими. Но для инициализации 'B.URL' требуется' A.HOST'. Таким образом, проблема в том, что 'A' еще не инициализируется, когда инициализируется' B.URL', это вызовет какие-либо проблемы или нет? – Blip

Смежные вопросы