0

I feel so dumb and confused, but this doesn't feel right at all.

System.out.println(false && true ^ true);

prints out false. I'm sure that java does and operation before the xor operation, so I theorized that with *&&*s, java just evaluates that whole expression to false the moment it sees a false in the and expression, but when I tested my theory with this expression down below

System.out.println(false && true || true);

it prints out true. Could someone explain this to me? This is really frustrating me.

sad
  • 1

3 Answers3

1

Bitwise operators have precedence over logical operators. So ^ has precedence over &&. So for:

false && true ^ true

you have:

false && true ^ true
false && false
false

&& has precedence over ||, so for:

false && true || true

you have:

false && true || true
false || true
true
CryptoFool
  • 21,719
  • 5
  • 26
  • 44
  • Why does everyone think that an operator between two boolean types is called bitwise? https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.22.2 – user15187356 Mar 25 '21 at 20:18
  • 1
    Because under the covers, it is still doing a bitwise operation. It's just that for a boolean value, bitwise and logical are equivalent. I suppose that's why Java didn't bother to define `^^`. From the Java SE spec you refer to: **"When both operands of a &, ^, or | operator are of type boolean or Boolean, then the type of the bitwise operator expression is boolean."**. That quote shows that Sun considered the operator to be bitwise even between booleans. I don't know what you were getting from that same paragraph to argue otherwise. – CryptoFool Mar 25 '21 at 20:30
  • *"Bitwise operations have precedence over logical operations"* Wrong. E.g. bitwise `&` and logical `&` have the same precedence. Operator precedence is that `&` > `^` > `|` > `&&` > `||`, so you are correct that `false && true ^ true` evaluates as `false && (true ^ true)`, but both `&&` and `^` are logical operators in that expression. – Andreas Mar 25 '21 at 20:35
  • 1
    Oops...I really meant "bitwise operatORS". I'll fix that. I was not suggesting that the context in which a particular operator appears changes its precedence. - The question I guess we're still battling here is if it makes any difference which label you put on the "bitwise operators", "logical" or "bitwise", when they're applied to pairs of boolean values. Since I've never had that distinction matter to me, and I can't think why it would, I'm personally not all that interested in the issue. I consider it semantics, not anything technically relevant. But I'm ready to be otherwise educated – CryptoFool Mar 25 '21 at 20:39
  • @Andreas - can you point to where it is discussed or defined that there is such a thing as "logical `&`"? I see your very intelligent comments a lot here on SO, so I'm asking this with all due respect and a desire to learn. This is just something I never thought to make a distinction on. Does it ever matter which way you look at it? For two booleans, does the JRE do a bitwise operation or not? If it doesn't, does it do us any good to know that? – CryptoFool Mar 25 '21 at 20:50
  • My link points to the JLS page describing `logical &`. Underneath that is `conditional &&`. – user15187356 Mar 25 '21 at 21:03
  • 1
    The expressions `True << True` and `(True ^ False) << True` not only yield valid and "truthy" values, but they both yield the value `2`. This suggest pretty strongly that the JRE is quite willing and able to treat `True` and `False` like `1` and `0`. Given this, why would one not consider `True ^ False` to be a bitwise operation that first yields the value `1 ^ 0 == 1` under the covers, and then is presented as boolean `true` by the JRE? – CryptoFool Mar 25 '21 at 21:04
  • On most computer instruction sets, which I take to include the JVM, 'integer and' and 'boolean and' are the same instruction. But that doesn't make them conceptually the same thing at the language level. We have higher-level languages precisely to impose higher-level constructs on raw bits. – user15187356 Mar 25 '21 at 21:06
  • 1
    @user15187356 - I see...the heading of the section. I believe that's just semantics. It's saying that the end result can be seen as logical because what else can you do with boolean values? But the details say that the "operators" are still "bitwise". Also, if you look at the new answer by WJS, it shows that even though the operands are booleans, an integer XOR is performed. – CryptoFool Mar 25 '21 at 21:07
  • Well, of course its semantics. That's what the JLS is describing - the semantics (and syntax) of constructions in the language. – user15187356 Mar 25 '21 at 21:09
  • 1
    If we're talking semantics, then I don't care one way or the other. Unless it matters which label you put on something as to how it operates, the distinction is meaningless. I've considered the distinction meaningless for my entire Java career, which started with the beta of Java 1.0. If it's technically meaningless, then it's meaningless for the purpose of my answer. I guess we're still talking about this because I said "logical operation" rather than "logical operator" because I consider them to be the same. Since others don't, I amended my answer to make the distinction irrelevant. – CryptoFool Mar 25 '21 at 21:12
  • @CryptoFool "JLS 15.22.1. Integer **Bitwise** Operators `&`, `^`, and `|`", vs "JLS 15.22.2. Boolean **Logical** Operators `&`, `^`, and `|`". --- This is Java, and there is no such thing as `True`. There is `true` and `Boolean.TRUE`, and `true << true` does not compile, so `(True ^ False) << True` certainly doesn't yield the value `2`. --- How Java code translates to byte code is immaterial to the *language*. Java's strong typing *never* equivalences `boolean` and numeric values, i.e. a `boolean` is not a number and there is no truthiness in a number. – Andreas Mar 25 '21 at 22:19
  • The really messed up part is that, assuming *no side-effects* of the operands, `&&` and `&` should yield the same logical result. However, `false && true ^ true` and `false & true ^ true` do not do that, because of operator precedence: `false && true ^ true` → `false && (true ^ true)` → `false && false` → **`false`**, but `false & true ^ true` → `(false & true) ^ true` → `false ^ true` → **`true`**. The precedence of the actual operators matter, not the bitwise vs logical, so saying "bitwise have precedence over logical" (like this answer is saying) is a meaningless (incomplete) statement. – Andreas Mar 25 '21 at 22:35
0

The bottom line is that XOR is higher precedence. So false will be evaluated first and since it followed by and AND the rest of the statement is not evaluated (&& short circuited the evaluation). But if you want to see it in action, here goes. In the example, I assign to local variables, otherwise the compiler in its infinite wisdom, will pre-evaluate the constants (like your example) and obtain the result. So it was never really executed by the JVM.

Given the following code:

boolean f  = false;
boolean t1 = true;
boolean t2 = true;
boolean result = f && t1 ^ t2;

Here is the byteCode with explanations

  public static void main(java.lang.String[] args);
     0  iconst_0                // int 0 represents false
     1  istore_1 [f]            // store at f slot
     2  iconst_1                // int 1 represents true
     3  istore_2 [t1]           // store at t1 slot
     4  iconst_1               
     5  istore_3 [t2]           // same for t2
     6  iload_1 [f]             // load f onto stack
     7  ifeq 20                 // if equal to 0 (false), go to 20 and store 0 in boolean
                                // result.  This is the first indication that
                                // false was evaluated in isolation since false && any
                                // thing else would return false. So the XOR need not be 
                                // evaluated.  In your case it was `dead code`. But if `f` 
                                // were actually set to true.. 
    10  iload_2 [t1]            // load t1 and t2 on stack
    11  iload_3 [t2]            // 
    12  ixor                    // now do the XOR
    13  ifeq 20                 // if result is true, statement is true
                                // Remember! We're only here because f was true.

    16  iconst_1                // and load 1 (true onto stack) and store in result
    17  goto 21                 // else fall thru and store 0 in result.
    20  iconst_0
    21  istore 4 [result]
    23  return


WJS
  • 36,363
  • 4
  • 24
  • 39
-2

^ is a bitwise operator in Java.

Based on this page about Java Operators, the bitwise XOR has a higher priority than the logical operators. In addition, the logical AND has a higher priority than the logical OR, and so your two statements are really:

System.out.println(false && (true ^ true)); // false && false -> false
System.out.println((false && true) || true); // false || true -> true
lucasvw
  • 1,345
  • 17
  • 36
  • 1
    ^ is a bitwise operator when used between integer values. It is a [logical operator](https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.22.2) when used between boolean values. – user15187356 Mar 25 '21 at 20:14
  • @user15187356 I think there is no difference in meaning. The link you gave has the following text under the header "Boolean Logical Operators": " then the type of the *bitwise operator* expression is boolean" – lucasvw Mar 25 '21 at 20:20