Приоритет и назначения Java-операторов [дубликат]

Мы не можем привязать это к setTimeout(), поскольку он всегда выполняется с глобальным объектом (Window), если вы хотите получить доступ к контексту this в функции обратного вызова, а затем с помощью bind() к функции обратного вызова, которую мы можем достичь как:

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);
40
задан frunkad 17 December 2015 в 19:55
поделиться

5 ответов

Выражения оцениваются слева направо. Скобки (и приоритет) просто выражают группировку, они не выражают порядок оценки.

Итак,

 11 * (12 + 5)
++a   ++a

равно

187
95
ответ дан Sotirios Delimanolis 22 August 2018 в 09:46
поделиться
  • 1
    @Zippy Это утверждение вводит в заблуждение, если оно не ошибочно. Скобки не являются операторами. Выражение между круглыми скобками - это еще один тип выражения. Приоритет операторов к ним не применяется. Приоритет оператора - это всего лишь механизм определения того, какое выражение (-ы) операндов привязывается к оператору . В примере OP, из-за (), ++a и 5 считаются операндами +. Результатом этого выражения и ведущего ++a считаются операнды *. – Sotirios Delimanolis 26 October 2017 в 20:34
  • 2
    Предположим, что у меня есть выражение x ++ + y, Учитывая ограничение для порядка приоритета в ссылке introcs.cs.princeton.edu/java/11precedence , можно сказать, что операнд x делится на два оператора ++ (post increment) и + (дополнение) операторов? – redeemed 14 November 2017 в 16:58
  • 3
    @redeemed Избавиться от этой ссылки полностью. Половина тех вещей, которые они описывают как операторов, не являются. Это очень вводит в заблуждение. Для выражения типа x++ + y вы можете сказать, что операндом для ++ является выражение (переменная) x и что операнды для + - это выражения x++ и (переменная) y , – Sotirios Delimanolis 14 November 2017 в 17:10
  • 4
    Что, если выражение было ++ x + y, в таком случае, можно сказать, что x является общим для операторов ++ и +? – redeemed 14 November 2017 в 17:23
  • 5
    @redeemed Не думайте об этом как shared . Но нет, вы не можете. Все выражение ++x является одним из операндов +, а не только переменной x. – Sotirios Delimanolis 14 November 2017 в 17:24
  int a = 10;
  a = ++a * ( ++a + 5);

выше вида выражений всегда оцениваются слева направо так: C или JAVA

в этом случае он решает аналогично 11 * (12 + 5), что приводит к 11 * 17 = 187 // wrt java

, но если он решает одно и то же выражение по C-language

, тогда ответ изменяется как способ оценки изменений

в c происходит первый предварительный приращение / предварительный декремент, поэтому, если в выражении есть «N», то в выражении нет inc inc / dec, тогда inc / dec произойдет сначала «N» no times

то одно и то же значение будет заменено в каждом вхождении переменной в выражение и вычисляется значение выражения и после этого происходит приращение / декремент post

, т.е. a увеличивается с шагом 11, затем снова 12, так как есть два приращение для a в выражении, а затем выражение оценивается как

12 * (12 + 5) = 12 * 17 = 204 // wrt C-language

-1
ответ дан Debpratim Ghosh 22 August 2018 в 09:46
поделиться
  • 1
    Порядок оценки не обязательно слева направо в C. Все. Вы написали о C здесь, не имеет отношения к вопросу и должны быть удалены. – user207421 20 December 2015 в 02:25

Цитата из Блог Эрика Липперта :

Оценка арифметического выражения контролируется тремя наборами правил: правилами приоритета, правилами ассоциативности и правилами порядка.

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

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

Порядок правил оценки описывает порядок, в котором оценивается каждый операнд в выражении.

Более высокий приоритет приводит к группировке операндов с помощью оператора и не означает оценку операндов. Это порядок оценки, который определяет последовательность оценки подвыражений в выражении.


Обновление:

Как я вижу, многие программисты считают, что оператор

a = ++a * ( ++a + 5);  

будет вызывать неопределенное поведение. Да, он будет вызывать UB, если нет гарантии порядка оценки операндов оператора.

Но это не так в контексте языка Java-программирования. Он имеет четко определенное поведение в java (а также в C #). Спецификация языка Java гласит, что:

15.7. Порядок оценки

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

Пример 15.7.1-1. Левый операнд оценивается сначала

В следующей программе оператор * имеет левый операнд, который содержит назначение переменной и правый операнд, содержащий ссылку к той же переменной. Значение, созданное ссылкой, будет отражать тот факт, что назначение произошло первым.

class Test1 {
    public static void main(String[] args) {
        int i = 2;
        int j = (i=3) * i;
        System.out.println(j);
    }
}

Эта программа производит вывод:

9

Не разрешено для оценка оператора * для получения 6 вместо 9 .

Но, по-прежнему спецификация java четко заявляет, что не писать такие коды:

Рекомендуется, чтобы код не опирался на эту спецификацию. Код обычно более ясен, когда каждое выражение содержит не более одного побочного эффекта, как его внешнюю операцию, и когда код не зависит от того, какое именно исключение возникает из-за оценки выражений слева направо.

28
ответ дан haccks 22 August 2018 в 09:46
поделиться
  • 1
    Спасибо за крик. Я отмечаю, что в статье в блоге речь идет о C #, но в этом случае правила на C # и Java одинаковы. – Eric Lippert 29 January 2015 в 18:47
  • 2
    @EricLippert; Да. Я знаю. Речь идет о C #, но определение, которое вы там предоставили для приоритета , ассоциативности и порядок оценки подходит для любого языка программирования, AFAIK. – haccks 29 January 2015 в 18:54
  • 3
    @haccks: Эти правила относятся к языкам с инфиксными операторами. Языки с чисто постфиксными или чисто префиксными операторами им не нужны. 2 3 4 + * однозначно (3 + 4) * 2 = 14. – MSalters 29 January 2015 в 20:54

Из этого фрагмента

int a = 10;
a = ++a * ( ++a + 5);

Иногда наиболее простым решением является использование javap для понимания порядка оценки:

 0: bipush 10 // push 10 onto the stack (stack={10})
 2: istore_1  // store 10 into variable 1 (a = 10, stack={})
 3: iinc 1, 1 // increment local variable 1 by 1 (a = 11, stack={})
 6: iload_1   // push integer in local variable 1 onto the stack (a = 11, stack = {11})
 7: iinc 1, 1 // increment local variable 1 by 1 (a = 12, stack={11})
 10: iload_1  // push integer in local variable 1 onto the stack (a = 12, stack = {12, 11})
 11: iconst_5 // load the int value 5 onto the stack (a = 12, stack = {5, 12, 11})
 12: iadd     // add 5 and 12 (a = 12, stack = {17, 11})
 13: imul     // multiply 17 and 11 (a = 12, stack = {})
  1. a увеличивается на 1. (строка 3) // a = 11
  2. a увеличивается на 1. (строка 7) // a = 12
  3. добавляет 5 в a (строка 12) // a = 17
  4. умножить 11 на 17 (строка 13) // a = 187

(10 + 1 + 1 + 5) * 11 = 187

10
ответ дан Pier-Alexandre Bouchard 22 August 2018 в 09:46
поделиться

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

(a()+b()) * (c()+d())
a() + (b()*c()) + d()

Скобки не должны (и в Java не могут) влиять на порядок, в котором вызываются вызовы a (), b (), c () и d (). Они могут повлиять на то, выполняется ли умножение до или после вызова d (), но только в очень редких случаях (например, d () вызывает интерфейс Java Native, который изменяет режим численного округления, используемый в умножении, способом, которым Java не знает about) будет иметь какой-либо способ узнать или заботиться о том, выполнялось ли умножение до или после d ().

В противном случае важно то, что в первом случае одна операция добавления будет действовать на () и b (), а другой - на c () и d (); умножение будет действовать на () + b () и c () + d (). В другом случае первое умножение будет действовать на b () и c (), первое сложение на a () и вышеупомянутое произведение, а второе сложение на первую сумму и d ().

2
ответ дан supercat 22 August 2018 в 09:46
поделиться
  • 1
    Привет @supercat. Говорят, что скобки имеют приоритет над операторами ++ (и -). В чем смысл этого, если мы изначально работаем слева направо, делая наши пост-приращения через все выражение, , тогда начинают учитывать скобки для последующего порядка операций? Означает ли это, что операторы пост-инкремента и пост-декремента имеют приоритет над любыми операциями в скобках, поскольку мы должны делать первые в первую очередь? Все еще путайте это! Благодарю. – Zippy 26 October 2017 в 20:29
  • 2
    @Zippy: операторы Java ++ и -- имеют смысл только для переменных примитивного типа или для индексированных массивов примитивов. В выражении, подобном ++x[a()+b()];, приращение не может произойти до тех пор, пока не будут обработаны вызовы для обоих a() и b(); произвольное количество функций может быть принудительно выполнено до инкремента, заключая их в скобки. Однако я не думаю, что подобная ситуация может возникать в Java с круглыми скобками, поскольку такие операторы, как +, -, * и т. Д., Дают то, с чем не могут действовать ++, -- , ни .. – supercat 26 October 2017 в 20:39
Другие вопросы по тегам:

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