Применить условное ИЛИ к переменной - PullRequest
2 голосов
/ 18 октября 2019

Имея переменную, инициализированную нулем, я хочу изменить ее значение, если есть значение, отличное от нуля по сравнению с ним. Эта вещь работает в Javascipt, но, кажется, не в Java.

int val = 0;
for (int i = 0; i < anArrayOfObjects.length; i++) {
    val = val || anArrayOfObjects[i].length;
}
return val;

Ошибка говорит:

Оператор '||'не может быть применено к 'int', 'int'

Как это должно быть изменено для работы?

Ответы [ 6 ]

3 голосов
/ 18 октября 2019

Чтобы дать некоторый контекст (другие ответы охватывают «способ Java», чтобы сделать это уже), понятие, что значение 0 - «ложь», обычно упоминается как «на этом языке, 0 - ложь» . В большинстве языков вещи являются правдивыми (если они используются в месте, где допустим только логический, он обрабатывается так же, как true), если только они не находятся в явном списке falsy вещей.

Проблема в том, что языки не совпадают в списке. Это вызывает бесконечную путаницу. null и undefined (если язык имеет понятие) универсально ложны. Но после этого все усложняется. Пустая строка ложная? Пустой список? Как насчет пользовательского типа данных, который имеет опцию итератора, и если бы вы вызывали его, он не возвращал бы никаких элементов? Например, объект-селектор jQuery, который ссылается на 0 элементов DOM, это truey или falsy ?

Как насчет строки "0"? Это действует как int 0 во многих местах, так должно ли оно быть ложным?

Даже более странно, в оболочках Linux (таких как /bin/bash), ситуация с числами обратная;0 является правдой, а все остальные значения ложными. Это кажется нелепым, но на самом деле имеет смысл в пределах того, для чего предназначены bash и тому подобное: процессы могут возвращать один байт как «значение ошибки», а 0 - универсальный индикатор «нет ошибки»;все нормально », поэтому bash работает с обратными значениями« истина / ложь ». истинное совпадение с «без ошибок» и ложное совпадение с «некоторыми ошибками», что является разумным способом сделать это.

Что приводит нас к Java: Java решила, что несколько символов были сохранены, имея в языке истинность / ложьабсолютно никоим образом не стоит сложности и путаницы, которые повлекут за собой его добавление. Таким образом, Ява является абсолютной. true это правда. false это фальшивка. Все остальные значения, если они используются в логическом контексте, являются ошибкой компилятора.

То есть: нет, java не позволяет использовать someIntExpr || defaultValue как быстрый способ переписать значение 0, и, что важно, никогда* будем. Попробуйте для этого someIntExpr == 0 ? defaultValue : someIntExpr или интегрируйте его прямо в вызов API, поэтому вместо записи: someHashMap.get("someKey") || "default", который не является Java и не будет компилироваться, попробуйте: someHashMap.getOrDefault("someKey", "default"). Это не единственный API Java, который имеет встроенную поддержку для передачи значений по умолчанию.

*) Мнения могут меняться, конечно, но давайте скажем так: чрезвычайно маловероятно, что достаточносообщество и основные коммиттеры передумали бы по этому поводу и позволили бы языковым изменениям ввести больше правдивых и ложных вещей.

3 голосов
/ 18 октября 2019

Из JLS - 15,24. Оператор условного оператора || :

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

Вам нужно обработать это по-другому, возможно, что-то вроде:

val = val != 0 ? val : anArrayOfObjects[i].length;

Логический оператор || в JavaScript может использоваться слюбое примитивное значение или объект. Его результат будет основан на том, является ли значение истинным или ложным .

1 голос
/ 18 октября 2019
int val = 0;
for (int i = 0; i < anArrayOfObjects.length && val == 0; i++) {
    val = anArrayOfObjects[i].length;
}
return val;

Или

return Stream.of(anArrayOfObjects)    // Stream<T[]>
    .mapToInt(o -> o.length)          // IntStream
    .filter(len -> len != 0)
    .findFirst()                      // OptionalInt
    .orElse(0);                       // int
1 голос
/ 18 октября 2019

Вы можете написать троичный оператор.

val = val == 0 ? anArrayOfObjects[i].length : val;

По сути, вам нужно найти первый ненулевой anArrayOfObjects[i].length или вернуть 0, если его нет. Подход Stream API может быть более интуитивно понятным.

Stream.of(anArrayOfObjects)
        .mapToInt(i -> i.length)
        .filter(i -> i != 0)
        .findFirst()
        .orElse(0);
1 голос
/ 18 октября 2019

Вместо val = val || anArrayOfObjects[i];, возможно, попробуйте
val = (anArrayOfObjects[i] > 0 ? anArrayOfObjects[i] : val)

. Это обновляет val новым значением, только если оно больше 0.

0 голосов
/ 18 октября 2019

Попробуйте

1002 *
...