Java Language
Выражения
Поиск…
Вступление
замечания
Для справки о операторах, которые можно использовать в выражениях, см. Операторы .
Приоритет оператора
Когда выражение содержит несколько операторов, его потенциально можно читать по-разному. Например, математическое выражение 1 + 2 x 3
можно читать двумя способами:
- Добавьте
1
и2
и умножьте результат на3
. Это дает ответ9
. Если мы добавим круглые скобки, это будет выглядеть как( 1 + 2 ) x 3
. - Добавьте
1
к результату умножения2
и3
. Это дает ответ7
. Если мы добавим круглые скобки, это будет выглядеть как1 + ( 2 x 3 )
.
В математике соглашение состоит в том, чтобы читать выражение вторым способом. Общее правило заключается в том, что умножение и деление выполняются до сложения и вычитания. Когда используется более продвинутая математическая нотация, либо значение либо «самоочевидно» (для обученного математика!), Либо круглые скобки добавляются для устранения неоднозначности. В любом случае эффективность обозначений для передачи смысла зависит от интеллекта и общих знаний математиков.
В Java есть четкие правила о том, как читать выражение, основанное на приоритете используемых операторов.
В общем случае каждому оператору приписывается значение приоритета ; см. таблицу ниже.
Например:
1 + 2 * 3
Приоритет +
меньше приоритета *
, поэтому результат выражения равен 7, а не 9.
Описание | Операторы / конструкции (первичные) | старшинство | Ассоциативность |
---|---|---|---|
спецификатор Скобки Создание экземпляра Доступ к полям Доступ к массиву Вызов метода Ссылка на метод | имя . название ( expr ) new первичный . название primary [ expr ] primary ( expr, ... ) primary :: name | 15 | Слева направо |
Пошаговый прирост | expr ++ , expr -- | 14 | - |
Предварительное увеличение Одинарный В ролях 1 | ++ expr, -- expr, + expr, - expr, ~ expr ! выраж, ( тип ) expr | 13 | - Справа налево Справа налево |
Multiplicative | * /% | 12 | Слева направо |
присадка | + - | 11 | Слева направо |
сдвиг | << >> >>> | 10 | Слева направо |
реляционный | <> <=> = instanceof | 9 | Слева направо |
равенство | ==! = | 8 | Слева направо |
Побитовое И | & | 7 | Слева направо |
Побитовое исключение ИЛИ | ^ | 6 | Слева направо |
Побитовое включение ИЛИ | | | 5 | Слева направо |
Логические И | && | 4 | Слева направо |
Логический ИЛИ | || | 3 | Слева направо |
Условный 1 | ? : | 2 | Справа налево |
присваивание Лямбда 1 | = * = / =% = + = - = << = >> = >>> = & = ^ = | = -> | 1 | Справа налево |
1 Приоритет экспрессии Lambda является сложным, так как он также может возникать после литья или в качестве третьей части условного тернарного оператора.
Константные выражения
Постоянное выражение является выражением, которое дает примитивный тип или String, и значение которого может быть оценено во время компиляции до литерала. Выражение должно оцениваться без исключения исключения и должно состоять только из следующего:
Примитивные и строковые литералы.
Набирает типы для примитивных типов или
String
.Следующие унарные операторы:
+
,-
,~
и!
,Следующие бинарные операторы:
*
,/
,%
,+
,-
,<<
,>>
,>>>
,<
,<=
,>
,>=
,==
!=
,&
,^
,|
,&&
и||
,Тернарный условный оператор
?
:
.Ориентированные на скобки выражения.
Простые имена, относящиеся к постоянным переменным. (Постоянная переменная - это переменная, объявленная как
final
где выражение инициализатора само является константным выражением.)Квалифицированные имена формы
<TypeName> . <Identifier>
которые относятся к постоянным переменным.
Обратите внимание, что в приведенном выше списке исключаются ++
и --
, операторы присваивания, class
и instanceof
, вызовы методов и ссылки на общие переменные или поля.
Константные выражения типа String
приводят к «интернированной» String
, а операции с плавающей запятой в константных выражениях оцениваются с помощью FP-строгой семантики.
Использование для константных выражений
Константные выражения могут использоваться (примерно) в любом месте, где может использоваться нормальное выражение. Однако они имеют особое значение в следующих контекстах.
Для операторов case в операторах switch требуются константные выражения. Например:
switch (someValue) {
case 1 + 1: // OK
case Math.min(2, 3): // Error - not a constant expression
doSomething();
}
Когда выражение в правой части присваивания является постоянным выражением, тогда назначение может выполнять примитивное сужение преобразования. Это разрешено при условии, что значение константного выражения находится в пределах диапазона типа с левой стороны. (См. JLS 5.1.3 и 5.2 ) Например:
byte b1 = 1 + 1; // OK - primitive narrowing conversion.
byte b2 = 127 + 1; // Error - out of range
byte b3 = b1 + 1; // Error - not a constant expession
byte b4 = (byte) (b1 + 1); // OK
Когда константное выражение используется как условие в do
, while
или for
, то оно влияет на анализ читаемости. Например:
while (false) {
doSomething(); // Error - statenent not reachable
}
boolean flag = false;
while (flag) {
doSomething(); // OK
}
(Обратите внимание , что это не относится , if
заявления. Компилятор Java позволяет then
или else
блок , if
оператор будет недоступен. Это аналог Java условной компиляции в C и C ++.)
Наконец, static final
поля в классе или интерфейсе с постоянными инициализаторами выражения инициализируются с нетерпением. Таким образом, гарантируется, что эти константы будут наблюдаться в инициализированном состоянии, даже если в графике зависимостей инициализации класса есть цикл.
Для получения дополнительной информации см. JLS 15.28. Константные выражения .
Порядок оценки выражений
Выражения Java оцениваются по следующим правилам:
- Операнды оцениваются слева направо.
- Операторы оператора оцениваются перед оператором.
- Операторы оцениваются в соответствии с приоритетом оператора
- Списки аргументов оцениваются слева направо.
Простой пример
В следующем примере:
int i = method1() + method2();
порядок оценки:
- Левый операнд оператора
=
вычисляется по адресуi
. - Вычисляется левый операнд оператора
+
(method1()
). -
method2()
правый операнд оператора+
(method2()
). -
+
операция+
. - Операция
=
вычисляется, присваивая результат добавления кi
.
Обратите внимание, что если эффекты вызовов наблюдаемы, вы сможете заметить, что вызов method1
происходит до вызова method2
.
Пример с оператором, который имеет побочный эффект
В следующем примере:
int i = 1;
intArray[i] = ++i + 1;
порядок оценки:
- Вычисляется левый операнд оператора
=
. Это дает адресintArray[1]
. - Оценивается предварительный прирост. Это добавляет
1
кi
и оценивает до2
. - Проверяется правый операнд
+
. - Операция
+
оценивается как:2 + 1
->3
. - Операция
=
вычисляется, присваивая значение3
intArray[1]
.
Обратите внимание, что, поскольку левый операнд =
сначала оценивается, на него не влияет побочный эффект подвыражения ++i
.
Ссылка:
Основы экспрессии
Выражения в Java являются основной конструкцией для выполнения вычислений. Вот некоторые примеры:
1 // A simple literal is an expression
1 + 2 // A simple expression that adds two numbers
(i + j) / k // An expression with multiple operations
(flag) ? c : d // An expression using the "conditional" operator
(String) s // A type-cast is an expression
obj.test() // A method call is an expression
new Object() // Creation of an object is an expression
new int[] // Creation of an object is an expression
В общем случае выражение состоит из следующих форм:
- Имена выражений, которые состоят из:
- Простые идентификаторы; например,
someIdentifier
- Квалифицированные идентификаторы; например
MyClass.someField
- Простые идентификаторы; например,
- Первичные, состоящие из:
- литералы; например,
1
,1.0
,'X'
,"hello"
,false
иnull
- Литеральные выражения класса; например,
MyClass.class
-
this
и<TypeName> . this
- Семантические выражения; например
( a + b )
- Выражения создания экземпляра класса; например,
new MyClass(1, 2, 3)
- Выражения создания экземпляра массива; например,
new int[3]
- Выражения доступа к полю; например
obj.someField
илиthis.someField
- Выражения доступа к массиву; например,
vector[21]
- Вызов метода; например
obj.doIt(1, 2, 3)
- Ссылки на методы (Java 8 и более поздние версии); например
MyClass::doIt
- литералы; например,
- Унарные выражения оператора; eg
!a
илиi++
- Бинарные выражения оператора; например
a + b
илиobj == null
- Тернарные выражения оператора; например
(obj == null) ? 1 : obj.getCount()
- Лямбда-выражения (Java 8 и более поздние версии); например
obj -> obj.getCount()
Подробности различных форм выражений можно найти в других разделах.
- В разделе « Операторы» рассматриваются унарные, двоичные и тернарные выражения операторов.
- В выражении лямбда-выражений рассматриваются лямбда-выражения и ссылочные выражения методов.
- Тема « Классы и объекты» охватывает выражения создания экземпляра класса.
- В разделе « Массивы» рассматриваются выражения доступа к массиву и выражения создания экземпляра массива.
- В литературной теме рассматриваются различные виды литературных выражений.
Тип выражения
В большинстве случаев выражение имеет статический тип, который можно определить во время компиляции путем изучения и его подвыражений. Они называются автономными выражениями.
Однако (в Java 8 и более поздних версиях) следующие выражения могут быть поли выражениями :
- Семантические выражения
- Выражения создания экземпляра класса
- Выражения вызова метода
- Справочные выражения метода
- Условные выражения
- Лямбда-выражения
Когда выражение является поли-выражением, на его тип может влиять целевой тип выражения; т.е. для чего он используется.
Значение выражения
Значение выражения - это присвоение, совместимое с его типом. Исключением является то, когда произошло загрязнение кучи ; например, потому что предупреждения «небезопасного преобразования» были (ненадлежащим образом) подавлены или проигнорированы.
Выражения выражений
В отличие от многих других языков, Java обычно не позволяет выражениям использоваться в качестве операторов. Например:
public void compute(int i, int j) {
i + j; // ERROR
}
Поскольку результат оценки такого выражения не может быть использован, и поскольку он не может повлиять на выполнение программы каким-либо другим способом, разработчики Java приняли позицию, что такое использование является либо ошибкой, либо ошибочным.
Однако это не относится ко всем выражениям. Подмножество выражений (фактически) является законным как утверждения. Набор содержит:
- Выражение присваивания, включая операции-и- назначения.
- Предварительные и последующие выражения приращения и уменьшения.
- Вызов метода (
void
илиvoid
). - Выражения экземпляра класса.