Приращение функции, перезаписанной + =

17

Метод, вызываемый в тройном операторе, приращает переменную и возвращает логическое значение. Когда функция возвращает false, значение возвращается. Я ожидал, что переменная будет 1, но вместо этого я получаю 0. Почему?

public class Main {
    public int a=0;//variable whose value is to be increased in function
    boolean function(){
        a++;
        return false;
    }
    public static void main(String argv[]){
        Main m=new Main();
        m.a+=(m.function()?1:0);
        System.out.println(m.a);//expected output to be 1 but got a 0 !!!!!
    }
}
    
задан Hitesh Kaushal 21.05.2016 в 06:33
источник
  • Разве это не должно быть неопределенным поведением? –  Patrick Roberts 21.05.2016 в 06:41
  • Неопределенное поведение - концепция C / C ++. –  John Kugelman 21.05.2016 в 06:42
  • @holidayCoder No. –  John Kugelman 21.05.2016 в 06:45
  • @LukePark, ваш первоначальный оператор все еще неверен, и именно это я указываю. Возвращаемое значение функции и только тернарный оператор не имеют ничего общего с конечным значением m.a. Это факт, что оператор + = каким-то образом заменяет состояние пост-приращения a. –  Patrick Roberts 21.05.2016 в 06:52
  • @PatrickRoberts Моя первоначальная инструкция не ошибается. Я думаю, вы неправильно понимаете этот приказ. Заменяя значения, это в значительной степени говорит m.a = 0 (текущее значение) + (потенциально 1 или 0). –  Luke Joshua Park 21.05.2016 в 06:54
Показать остальные комментарии

2 ответа

23

В основном m.a += (m.function() ? 1 : 0) компилируется в

 int t = m.a; // t=0 (bytecode GETFIELD)
 int r = m.function() ? 1  : 0; // r = 0 (INVOKEVIRTURAL and, IIRC, do a conditional jump)
 int f = t + r; // f = 0 (IADD)
 m.a = f // whatever m.a was before, now it is 0 (PUTFIELD)

Вышеуказанное поведение указано в JLS 15.26 .2 (выпуск JAVA SE 8)

    
ответ дан glee8e 21.05.2016 в 06:54
источник
  • Приобретено +1 для вас, но -1 для JLS является фолом в этом отношении. –  abligh 21.05.2016 в 17:57
19

У вас есть две операции, действующие на m.a в одном вызове; в main

m.a += (m.function()?1:0);

выталкивает значение a в фрейме, а затем вызывает m.function() (который возвращает false ), поэтому троянец расширяется до m.a += 0; (а значение m.a из фрейма добавляется к 0 и сохраняется в m.a ). Таким образом, значение увеличивается в m.function() (а затем reset в main ). Рассмотрим это так,

m.a = m.a + (m.function() ? 1 : 0);

Значение m.a определяется до оценки m.function() (таким образом, это операция приращения по почте). Для результата expected вы могли бы сделать

m.a = (m.function() ? 1 : 0) + m.a;
    
ответ дан Elliott Frisch 21.05.2016 в 06:44
источник
  • Почему он оценивается таким образом? Можете ли вы привести источники JLS, которые охватывают это? –  John Kugelman 21.05.2016 в 06:47
  • Итак, поведение связано с вызовами стека? –  Patrick Roberts 21.05.2016 в 06:47
  • функция возвращает false, что означает, что она 0, а в действии она неверна, поэтому функция m.function ()? 1: 0 также возвращает 0 ?? –  emotionlessbananas 21.05.2016 в 06:49
  • Я был, пожалуй, неясен, он действительно не связан с тройным, это из-за использования оператора post increment. –  Elliott Frisch 21.05.2016 в 06:50
  • docs.oracle.com/javase/specs/jls/se8/html/... объясняет, как оцениваются сложные назначения @JohnKugelman. –  Codebender 21.05.2016 в 06:54
Показать остальные комментарии