2012-01-31 3 views
24

Документация на языке Java гласит: «Если примитивный тип или строка определяется как константа, а значение известно во время компиляции, компилятор заменяет имя константы всюду в коде своим значением. называется константой времени компиляции ».Константы и переменные времени компиляции

Так я понимаю, если у нас есть кусок кода:

private final int x = 10; 

Тогда компилятор заменит каждое вхождение «х» в коде с буквальным «10». Но говорит, предположит, что константа инициализируются со значением во время выполнения,

private final int x = getX(); // here getX() returns an integer value at run-time. 

Будет ли падение производительности (какой бы незначительное), может быть по сравнению с константой во время компиляции?

Другой вопрос, является ли ниже строка кода:

private int y = 10; // here y is not final 

обрабатывают так же, как время компиляции постоянной компилятором?

EDIT: Наконец, то, что я понял из ответов являются:

  1. final static означает время компиляции постоянной
  2. просто final означает, что его постоянная, но инициализируется во время выполнения
  3. просто static означает, что инициализировано во время выполнения
  4. без final является переменной и не будет считаться константой.

Насколько я понял правильно?

+5

о пункте 2. Вы ошибаетесь! final int a = 1; a - постоянная времени компиляции. final int b; b = 1; b не является – landry

ответ

41

Compile постоянного время должны быть:

  • объявлен окончательный
  • примитивными или Строка
  • инициализируется в декларации
  • инициализирован с постоянным выражением

Так private final int x = getX(); не является постоянная ,

К второму вопросу private int y = 10; не является постоянным (в данном случае не конечным), поэтому оптимизатор не может быть уверен, что значение не изменится в будущем. Поэтому он не может оптимизировать его так же хорошо, как постоянное значение. Ответ: Нет, он не обрабатывается так же, как константа времени компиляции.

+2

JLS, определяющий постоянное выражение: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 –

+1

еще один пример, чтобы устранить сомнение: final int a = 1; является константой времени компиляции, но final int a; а = 2; не –

+0

Я думаю, что он может быть инициализирован внутри декларации или внутри constuctor –

1

Там может быть действительно небольшое падение производительности на некоторые машины для private final int x = getX();, поскольку это будет включать в себя по крайней мере один вызов метода (кроме того факта, что это не время компиляции постоянной), но, как вы сказал, было бы пренебрежимо малым так зачем беспокоиться?

Что касается второго вопроса: y не является окончательным и, следовательно, не является константой времени компиляции, поскольку он может меняться во время выполнения.

1

private final int x = getX(); Будет называться в первый раз, когда объявлен ваш объект. «Падение» производительности будет зависеть от getX(), но это не то, что нужно для создания узкого места.

2

Ключевое слово final означает, что переменная будет инициализирована один раз и только один раз. Действительная константа должна быть объявлена ​​static. Итак, ни один из ваших примеров не компилируется как константы. Тем не менее последнее ключевое слово сообщает вам (и компилятору), что ваши переменные будут инициализированы только один раз (в конструкторе или буквально). Если вам нужны их значения, назначенные во время компиляции, ваши поля должны быть статическими.

Производительность на самом деле не так затронута, но имейте в виду, что примитивные типы неизменяемы, как только вы их создали, он будет хранить это значение в памяти до тех пор, пока сборщик мусора не удалит его. Итак, если у вас есть переменная y = 1;, а затем вы меняете ее на y = 2;, то в памяти JVM будет иметь оба значения, но ваша переменная будет «указывать» на последнюю.

частный int y = 10; // здесь y не является окончательным

обрабатывается компилятором так же, как время компиляции компилятора?

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

0

Согласно JLS, нет требования, чтобы «постоянная переменная» была статической.

Так что «постоянная переменная» может быть статичной или нестатической (переменная экземпляра).

Но JLS накладывает некоторые другие требования к переменному, чтобы быть «постоянной переменным» (кроме того только окончательными):

  • будучи единственной строкой или примитивный
  • инициализирован рядным только потому, что он является окончательным, и пустые окончательный не допускаются
  • инициализируются с «постоянным выражением» = «время компиляции константы выражения» (см JLS цитаты ниже)

4.12.4. final Variables (JLS)

A постоянной переменной является окончательным переменной примитивного типа или типа String, который инициализируется с постоянным выражением (§15.28).

15.28. Constant Expressions

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

Литералы примитивного типа и литералы типа String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)

Броски для примитивных типов и отливок типа String (§15.16)

Унарные операторы +, -, ~, и! (Но не ++ или -) (§15.15.3, §15.15.4, §15.15.5, §15.15.6)

мультипликативные операторы *,/и% (§15.17)

аддитивные операторы + и - (§15.18)

операторы сдвига < <, >> и >>> (§15.19)

операторы отношения <, < =,> и> = (но не instanceof) (§15.20)

Операторы равенства == и! = (§15.21)

Побитовые и логические операторы &,^и | (§15.22)

Условный оператор и оператор & & и условный оператор или оператор || (§15.23, §15.24)

Тернарный условный оператор? : (§15.25)

Обозначенные в скобках выражения (§15.8.5), содержащее выражение, является постоянным выражением .

Простые имена (§6.5.6.1), которые относятся к постоянным переменным (§4.12.4).

Квалифицированные имена (§6.5.6.2) формы TypeName. Идентификатор, который относится к постоянным переменным (§4.12.4).