Почему мы обычно используем `||` not `|`, в чем разница?
Мне просто интересно, почему мы обычно используем логический OR ||
между двумя булевыми не побитовыми OR |
, хотя они оба хорошо работают.
Я имею в виду, посмотрите на следующее:
if(true | true) // pass
if(true | false) // pass
if(false | true) // pass
if(false | false) // no pass
if(true || true) // pass
if(true || false) // pass
if(false || true) // pass
if(false || false) // no pass
Можно ли использовать |
вместо ||
? То же самое с &
и &&
.
Ответы
Ответ 1
Если вы используете формы ||
и &&
, а не формы |
и &
этих операторов, Java не будет пытаться оценить только правый операнд.
Это вопрос, хотите ли вы провести короткую замыкание оценки или нет - большую часть времени вы хотите.
Хорошим способом проиллюстрировать преимущества короткого замыкания было бы рассмотреть следующий пример.
Boolean b = true;
if(b || foo.timeConsumingCall())
{
//we entered without calling timeConsumingCall()
}
Еще одно преимущество, как упоминал Джереми и Питер, для короткого замыкания - это нулевая контрольная проверка:
if(string != null && string.isEmpty())
{
//we check for string being null before calling isEmpty()
}
подробнее
Ответ 2
|
не выполняет оценку короткого замыкания в логических выражениях. ||
перестанет оценивать, если первый операнд истинен, но |
не будет.
Кроме того, |
может использоваться для выполнения операции побитового ИЛИ со значениями байтов/коротких/целых/длинных. ||
не могу.
Ответ 3
Итак, просто для того, чтобы основываться на других ответах с примером, короткое замыкание имеет решающее значение в следующих защитных проверках:
if (foo == null || foo.isClosed()) {
return;
}
if (bar != null && bar.isBlue()) {
foo.doSomething();
}
Использование |
и &
вместо этого может привести к появлению NullPointerException
.
Ответ 4
Логический ||
и &&
проверять правую сторону только при необходимости. |
и &
проверить обе стороны каждый раз.
Например:
int i = 12;
if (i == 10 & i < 9) // It will check if i == 10 and if i < 9
...
Перепишите это:
int i = 12;
if (i == 10 && i < 9) // It will check if i == 10 and stop checking afterward because i != 10
...
Другой пример:
int i = 12;
if (i == 12 | i > 10) // It will check if i == 12 and it will check if i > 10
...
Перепишите это:
int i = 12;
if (i == 12 || i > 10) // It will check if i == 12, it does, so it stops checking and executes what is in the if statement
...
Ответ 5
Также обратите внимание на общую ошибку: у ленивых операторов есть приоритет над ленивыми, поэтому:
boolean a, b, c;
a || b && c; //resolves to a || (b && c)
a | b && c; //resolves to (a | b) && c
Будьте осторожны при их смешивании.
Ответ 6
В дополнение к короткому замыканию, еще одна вещь, о которой следует помнить, заключается в том, что выполнение побитовой логической операции над значениями, которые могут быть отличными от 0 или 1, имеет совсем другое значение, чем условная логика. Хотя это ИСПОЛЬЗОВАНИЕ одинаково для |
и ||
, при &
и &&
вы получаете очень разные результаты (например, 2 & 4
равно 0/false, а 2 && 4
равно 1/true).
Если вещь, которую вы получаете от функции, на самом деле является кодом ошибки, и вы тестируете не-0-ness, это может иметь большое значение.
Это не такая уж большая проблема в Java, где вам нужно явно указывать тип для boolean или сравнивать с 0 или тому подобное, но на других языках с похожим синтаксисом (C/С++ и др.) это может быть довольно запутанным.
Также обратите внимание, что и и | может применяться только к значениям целочисленного типа, а не ко всему, что может быть эквивалентно логическому тесту. Опять же, на языках, отличных от Java, существует немало вещей, которые можно использовать в качестве логического с неявным сравнением != 0
(указатели, float, объекты с operator bool()
и т.д.) И побитовые операторы почти всегда бессмысленны в этих контекстах.
Ответ 7
Единственный раз, когда вы используете |
или &
вместо ||
или &&
, - это когда у вас очень простые булевы выражения, а стоимость короткой резки (т.е. ветки) больше, чем когда вы сохранить, не оценивая более поздние выражения.
Однако это микро-оптимизация, которая редко имеет значение, за исключением кода самого низкого уровня.
Ответ 8
|| является логическим или оператором, а | является поразрядным или оператором.
boolean a = true;
boolean b = false;
if (a || b) {
}
int a = 0x0001;
a = a | 0x0002;
Ответ 9
a | b: оценить b в любом случае
a || b: оценить b , только если a оценивает значение false
Ответ 10
В дополнение к тому, что | является побитовым оператором: || является оператором короткого замыкания - когда один элемент является ложным, он не будет проверять другие.
if(something || someotherthing)
if(something | someotherthing)
если что-то ИСТИНА, || не будет оценивать someotherthing, в то время как | Сделаю. Если переменные в ваших if-statement являются фактически вызовами функции, используя || возможно, сэкономит много времени.
Ответ 11
Java || и && операторы оценивают только правую часть булевского выражения, если им нужно. Это называется ленивой оценкой.
Эквивалентный код для || оператор
// Simulate
// if(b||c)
// doThis();
// else
// doThat();
if(b)
doThis();
else
if(c)
doThis();
else
doThat();
// Similar for &&
Это требует намного меньше времени для оценки определенных выражений. Однако иногда вы можете использовать | Оператор:
public boolean updateGlobal(){
global = 2;
return true;
}
if(false | updateGlobal()){
foo();
}
Поскольку правая часть выражения имеет побочный эффект, мы хотим, чтобы он оценивался независимо от того, что. Однако это довольно плохая практика.
Ответ 12
| is the binary or operator
|| is the logic or operator
Ответ 13
Операторы ||
и &&
называются условными операторами, а |
и &
называются побитовыми операторами. Они служат различным целям.
Условные операторы работают только с выражениями, которые статически оценивают до boolean
как с левой, так и с правой стороны.
Побитовые операторы работают с любыми числовыми операндами.
Если вы хотите выполнить логическое сравнение, вы должны использовать условные операторы, так как вы добавите какой-то тип безопасности в свой код.
Ответ 14
Замечание: Java имеет | =, но не || =
Пример того, когда вы должны использовать || когда первое выражение представляет собой тест, чтобы увидеть, будет ли взорвано второе выражение. например Использование одного | в следующем случае может возникнуть NPE.
public static boolean isNotSet(String text) {
return text == null || text.length() == 0;
}
Ответ 15
1). (выражение1 | выражение2), | оператор будет оценивать выражение2 независимо от того, является ли результат выражения1 истинным или ложным.
Пример:
class Or
{
public static void main(String[] args)
{
boolean b=true;
if (b | test());
}
static boolean test()
{
System.out.println("No short circuit!");
return false;
}
}
2). (выражение1 || выражение2), || оператор не будет оценивать выражение2, если выражение1 истинно.
Пример:
class Or
{
public static void main(String[] args)
{
boolean b=true;
if (b || test())
{
System.out.println("short circuit!");
}
}
static boolean test()
{
System.out.println("No short circuit!");
return false;
}
}
Ответ 16
Другие ответы хорошо отражают функциональную разницу между операторами, но ответы могут быть применены практически к каждому существующему C-производному языку. Вопрос помечен java, и поэтому Я постараюсь ответить конкретно и технически на язык Java.
&
и |
могут быть либо целочисленными побитовыми операторами, либо логическими логическими операторами. Синтаксис для Побитового и Логического Операторов (§15.22):
AndExpression:
EqualityExpression
AndExpression & EqualityExpression
ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression
InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression
Синтаксис EqualityExpression
определяется в §15.21, для которого требуется RelationalExpression
, определенная в §15.20, что, в свою очередь, требует ShiftExpression
и ReferenceType
, определенных в §15.19 и §4.3, соответственно. ShiftExpression
требует AdditiveExpression
, определенного в §15.18, который продолжает развиваться, определяя основные арифметические, унарные операторы и т.д. ReferenceType
сводится к различным способам представления типа. (В то время как ReferenceType
не содержит примитивные типы, в конечном итоге требуется определение примитивных типов, поскольку они могут быть типом измерения для массива, который является ReferenceType
.)
Побитовые и логические операторы обладают следующими свойствами:
- Эти операторы имеют различный приоритет, причем
&
имеет наивысший приоритет и |
самый низкий приоритет. - Каждый из этих операторов синтаксически лево-ассоциативный (каждая группа слева направо).
- Каждый оператор является коммутативным, если выражения операнда не имеют побочных эффектов.
- Каждый оператор ассоциативен.
- Побитовые и логические операторы могут использоваться для сравнения двух операндов числового типа или двух операндов типа
boolean
. Все остальные случаи приводят к ошибке времени компиляции.
Различие между тем, служит ли оператор в качестве побитового оператора или логического оператора, зависит от того, являются ли операнды "конвертируемыми в примитивный интегральный тип" (§4.2), или если они имеют типы boolean
или boolean
(§5.1.8).
Если операнды являются целыми типами, двоичная цифровая продвижка (§5.6.2) выполняется на обоих операндах, оставляя их как в качестве long
или int
для операции. Тип операции будет типом (продвинутых) операндов. В этот момент &
будет побитовым И, ^
будет побитовым исключением OR, а |
будет побитовым включением ИЛИ. (§15.22.1)
Если операнды boolean
или boolean
, при необходимости операнды будут подвергнуты распаковке преобразования (§5.1.8), а тип операции будет boolean
. &
приведет к true
, если оба операнда true
, ^
приведет к true
, если оба операнда будут разными, а |
приведет к true
, если любой из операндов true
. (§15.22.2)
Напротив, &&
является "Условным и Оператором" (§15.23) и ||
является "условным или оператором" (§15.24). Их синтаксис определяется как:
ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression
ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression
&&
похож на &
, за исключением того, что он оценивает только правый операнд, если левый операнд true
. ||
похож на |
, за исключением того, что он оценивает только правый операнд, если левый операнд false
.
Условный-И имеет следующие свойства:
- Условный и оператор синтаксически лево-ассоциативный (он группирует слева направо).
- Условный оператор и оператор полностью ассоциативен как по отношению к обеим побочным эффектам, так и по результату. То есть для любых выражений
a
, b
и c
оценка выражения ((a) && (b)) && (c)
дает тот же результат с теми же побочными эффектами, происходящими в том же порядке, что и оценка выражения (a) && ((b) && (c))
. - Каждый операнд условного оператора и оператора должен иметь тип
boolean
или boolean
, или возникает ошибка времени компиляции. - Тип условного выражения и выражения всегда
boolean
. - Во время выполнения первое выражение первого операнда оценивается; если результат имеет тип
boolean
, он подвергается распаковке преобразования (§5.1.8). - Если результирующее значение
false
, значение условного выражения и выражения false
и выражение операнда справа не оценивается. - Если значение левого операнда
true
, то вычисляется правое выражение; если результат имеет тип boolean
, он подвергается распаковке преобразования (§5.1.8). Результирующее значение становится значением условного и выражения. - Таким образом,
&&
вычисляет тот же результат, что и &
в операндах boolean
. Он отличается только тем, что выражение правого операнда оценивается условно, а не всегда.
Условный - или имеет следующие свойства:
- Условный или оператор синтаксически лево-ассоциативный (он группирует слева направо).
- Условный оператор или оператор полностью ассоциативен относительно обоих побочных эффектов и значения результата. То есть для любых выражений
a
, b
и c
оценка выражения ((a) || (b)) || (c)
дает тот же результат с теми же побочными эффектами, происходящими в том же порядке, что и оценка выражения (a) || ((b) || (c))
. - Каждый операнд условного оператора или оператора должен иметь тип
boolean
или boolean
, или возникает ошибка времени компиляции. - Тип условного выражения или выражения всегда
boolean
. - Во время выполнения первое выражение первого операнда оценивается; если результат имеет тип
boolean
, он подвергается распаковке преобразования (§5.1.8). - Если результирующее значение
true
, значение условного выражения или выражения true
и выражение в правой части операнда не оценивается. - Если значение левого операнда
false
, тогда вычисляется правое выражение; если результат имеет тип boolean
, он подвергается распаковке преобразования (§5.1.8). Результирующее значение становится значением условного выражения или выражения. - Таким образом,
||
вычисляет тот же результат, что и |
в операндах boolean
или boolean
. Он отличается только тем, что выражение правого операнда оценивается условно, а не всегда.
Короче говоря, как @JohnMeagher неоднократно указывал в комментариях, &
и |
являются, по сути, недолговечными булевыми операторами в конкретном случае операндов, являющихся либо boolean
, либо boolean
. При наличии хороших практик (т.е. Никаких побочных эффектов) это незначительное различие. Однако, если операнды не являются boolean
или boolean
s, операторы ведут себя очень по-разному: побитовые и логические операции просто не сравниваются хорошо на высоком уровне программирования Java.
Ответ 17
|| возвращает логическое значение посредством OR'ing двух значений (Thats, почему его называют ЛОГИЧЕСКИМ или)
IE:
if (A || B)
Вернет true, если либо A, либо B истинно, либо false, если они оба являются ложными.
| является оператором, который выполняет побитовое управление двумя значениями. Чтобы лучше понять побитовые операции, вы можете прочитать здесь:
http://en.wikipedia.org/wiki/Bitwise_operation
Ответ 18
Главное отличие состоит в том, что || и && экспонат "короткого замыкания", поэтому RHS будет оцениваться только в случае необходимости.
Например,
if (a || b) {
path1...
} else {
path2..
}
Выше, если a истинно, тогда b не будет проверен, а путь1 будет выполнен. Если | был использован, тогда обе стороны будут оцениваться, даже если "а" истинно.
Смотрите здесь и здесь, для немного больше информация.
Надеюсь, что это поможет.
Ответ 19
Не короткое замыкание может быть полезным. Иногда вы хотите убедиться, что два выражения оцениваются. Например, скажем, у вас есть метод, который удаляет объект из двух отдельных списков. Возможно, вы захотите сделать что-то вроде этого:
class foo {
ArrayList<Bar> list1 = new ArrayList<Bar>();
ArrayList<Bar> list2 = new ArrayList<Bar>();
//Returns true if bar is removed from both lists, otherwise false.
boolean removeBar(Bar bar) {
return (list1.remove(bar) & list2.remove(bar));
}
}
Если ваш метод вместо этого использовал условный операнд, он не смог бы удалить объект из второго списка, если первый список возвратил false.
//Fails to execute the second remove if the first returns false.
boolean removeBar(Bar bar) {
return (list1.remove(bar) && list2.remove(bar));
}
Это не удивительно полезно, и (как и в большинстве задач программирования) вы могли бы добиться этого другими способами. Но это используется для побитовых операндов.
Ответ 20
Основное отличие между ними состоит в том, что | сначала преобразует значения в двоичные, а затем выполняет бит или операцию. Между тем, || не преобразует данные в двоичные и просто выполняет выражение или выражение на нем в исходном состоянии.
int two = -2; int four = -4;
result = two | four; // bitwise OR example
System.out.println(Integer.toBinaryString(two));
System.out.println(Integer.toBinaryString(four));
System.out.println(Integer.toBinaryString(result));
Output:
11111111111111111111111111111110
11111111111111111111111111111100
11111111111111111111111111111110
Подробнее: http://javarevisited.blogspot.com/2015/01/difference-between-bitwsie-and-logical.html#ixzz45PCxdQhk
Ответ 21
Когда у меня появился этот вопрос, я создал тестовый код, чтобы получить представление об этом.
public class HelloWorld{
public static boolean bool(){
System.out.println("Bool");
return true;
}
public static void main(String []args){
boolean a = true;
boolean b = false;
if(a||bool())
{
System.out.println("If condition executed");
}
else{
System.out.println("Else condition executed");
}
}
}
В этом случае мы изменяем только значение слева, если условие добавляет a или b.
||
Сценарий, если левая сторона истинна [if (a || bool())]
output "If condition executed"
||
Сценарий, когда левая сторона ложна [if (b || bool())]
Output-
Bool
If condition executed
Conclusion of ||
При использовании ||
, правая сторона проверяет только, когда левая сторона ложна.
|
Сценарий, если левая сторона истинна [if (a | bool())]
Output-
Bool
If condition executed
|
Сценарий, когда левая сторона ложна [if (b | bool())]
Output-
Bool
If condition executed
Conclusion of |
При использовании |
, проверьте как левую, так и правую сторону.
Ответ 22
| = побитовое или, || = логика или
Ответ 23
Обычно я использую, когда есть оператор pre increment и post increment. Посмотрите на следующий код:
package ocjpPractice;
/**
* @author tithik
*
*/
public class Ex1 {
public static void main(String[] args) {
int i=10;
int j=9;
int x=10;
int y=9;
if(i==10 | ++i>j){
System.out.println("it will print in first if");
System.out.println("i is: "+i);
}
if(x==10 ||++x>y){
System.out.println("it will print in second if");
System.out.println("x is: "+x);
}
}
}
выход:
он будет печататься первым, если
Я: 11
он будет печатать во втором, если
x: 10
оба блока if
одинаковы, но результат отличается.
когда есть |
, оба условия будут оценены. Но если это ||
, он не будет оценивать второе условие, поскольку первое условие уже истинно.
Ответ 24
Есть много вариантов использования, предлагающих, почему вы должны идти за ||
, а не |
. В некоторых случаях использования необходимо использовать оператор |
для проверки всех условий.
Например, если вы хотите проверить проверку формы и хотите показать пользователю все недопустимые поля с текстом ошибок, а не только первое недопустимое поле.
Оператор ||
был бы,
if(checkIfEmpty(nameField) || checkIfEmpty(phoneField) || checkIfEmpty(emailField)) {
// invalid form with one or more empty fields
}
private boolean checkIfEmpty(Widget field) {
if(field.isEmpty()) {
field.setErrorMessage("Should not be empty!");
return true;
}
return false;
}
Итак, с приведенным выше фрагментом, если пользователь отправляет форму со всеми пустыми полями, ТОЛЬКО nameField
будет отображаться с сообщением об ошибке. Но, если вы измените его на,
if(checkIfEmpty(nameField) | checkIfEmpty(phoneField) | checkIfEmpty(emailField)) {
// invalid form with one or more empty fields
}
Он покажет правильное сообщение об ошибке в каждом поле, независимо от условий true
.
Ответ 25
После внимательного прочтения этой темы мне все еще неясно, соответствует ли использование |
в качестве логического оператора правилам шаблонов Java.
Я недавно изменил код в запросе на получение ответа, в котором комментарий
if(function1() | function2()){
...
}
пришлось изменить на
boolean isChanged = function1();
isChanged |= function2();
if (isChanged){
...
}
Какая фактически принятая версия?
В документации Java нет упоминания |
как логического оператора ИЛИ без короткого замыкания.
Не заинтересованы в голосовании, но больше в выяснении стандарта?!
Обе версии кода компилируются и работают как положено.
Ответ 26
|| является логическим или и | бит-бит или.
Ответ 27
Операторы Java
| побитовое, или || является логическим или.
Ответ 28
Взгляните на:
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/operators.html
| побитовое включение OR
|| является логическим ИЛИ
Ответ 29
| является побитовым оператором. || является логическим оператором.
Один принимает два бита и/или их.
Определяется истина (это ИЛИ). Если это верно или это правда, тогда ответ верен.
О, и люди-данги быстро отвечают на эти вопросы.