Почему порядок объявлений важен для статических инициализаторов?

Я использую APC и могу засвидетельствовать, что он может существенно уменьшить ЦП и нагрузку ввода-вывода на сервер приложений при поддержании высокого уровня удачного обращения в кэш. Это не только сохраняет Вас от необходимости скомпилировать, это может сохранить Вас от необходимости считать php файлы из диска вообще. (т.е. байт-коды подаются непосредственно от оперативной памяти, таким образом, это супер быстро), Это понижает скорость для рендеринга единственной страницы и увеличивает запросы в секунду сервер может обработать.

, Если Вы используете Redhat или CentOS, устанавливая APC, супер просто:

yum install php-devel httpd-devel php-pear
pecl install apc 
echo "extension=apc.so" > /etc/php.d/apc.ini
# if you're using SELinux:
chcon "system_u:object_r:textrel_shlib_t" /usr/lib/php/modules/apc.so
/etc/init.d/httpd restart

Вы спросили об оборотных сторонах. Единственный недостаток - то, что требуется некоторая память. Значение по умолчанию на APC составляет 30 МБ, но это может быть скорректировано, и стоимость определенной памяти больше, чем платежи за себя с увеличенной скоростью и показателем отклика.

6
задан Daniel Rikowski 27 July 2009 в 10:20
поделиться

6 ответов

Прежде всего, давайте обсудим, что такое «прямая ссылка» и почему она плохая. Прямая ссылка - это ссылка на переменную, которая еще не была инициализирована, и она не ограничивается только статическими инициализаторами. Это плохо просто потому, что, если они позволят, они дадут нам неожиданные результаты. Взгляните на этот фрагмент кода:

public class ForwardRef {
    int a = b; // <--- Illegal forward reference
    int b = 10;
}

Что должно быть j при инициализации этого класса? Когда класс инициализируется, инициализации выполняются в порядке от первого до последнего. Следовательно, можно ожидать, что строка

a = b; 

будет выполняться до:

b = 10; 

Во избежание такого рода проблем разработчики Java полностью запретили такое использование прямых ссылок.

РЕДАКТИРОВАТЬ

это поведение определяется разделом 8.3.2.3 Спецификаций языка Java :

Объявление члена должно появиться перед его использованием, только если член является экземпляром ( соответственно статическое) поле класса или интерфейса C и выполняются все следующие условия:

  • Использование происходит в экземпляре (соответственно статическом) инициализаторе переменной C или в экземпляре (соответственно статическом) инициализаторе C.

  • Использование не находится в левой части присвоения.

  • C - это самый внутренний класс или интерфейс, охватывающий использование.

Ошибка времени компиляции возникает, если любое из трех требований выше не выполнено.

10
ответ дан 8 December 2019 в 16:08
поделиться

попробуйте следующее:

class YourClass {
    static {
        myField = new HashSet<String>();
        YourClass.myField.add("test");
    }

    private static Set<String> myField;
}

он должен компилироваться без ошибок в соответствии с JLS ...
(не особо помогает, или?)

2
ответ дан 8 December 2019 в 16:08
поделиться

В Java все инициализаторы, статические или другие, оцениваются в том порядке, в котором они появляются в определении класса.

1
ответ дан 8 December 2019 в 16:08
поделиться

См. Правила для прямых ссылок в JLS . Вы не можете использовать прямые ссылки, если:

  • Использование происходит в экземпляре (соответственно статическом) инициализаторе переменной C или в экземпляре (соответственно статическом) инициализаторе C.
1
ответ дан 8 December 2019 в 16:08
поделиться

Чтобы уточнить ответ DFA:

Я думаю, что вас сбивает с толку правило «левой стороны» во втором пункте в JLS 8.2.3.2. В вашей инициализации myField находится слева. В вашем вызове для добавления он находится справа. Код здесь неявно:

boolean result = myField.add('test')  

Вы не оцениваете результат, но компилятор по-прежнему действует так, как будто он есть. Вот почему ваша инициализация проходит, а ваш вызов add () терпит неудачу.

Что касается , почему это так, я понятия не имею. Насколько я знаю, это вполне может быть сделано для удобства разработчиков JVM.

1
ответ дан 8 December 2019 в 16:08
поделиться

Я думаю, что вызов метода проблематичен, потому что компилятор не может определить, какой метод add () использовать без ссылочного типа для myField .

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

0
ответ дан 8 December 2019 в 16:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: