29

When you try to do something like this:

if (true ^ 1) {
  //do something
}

the compiler reasonably says that operator ^ is not defined for argument types boolean and int. But if you use it like this:

if (true ^ 1 > 0) {
  //do something
}

the code compiles (for Java 8 at least) and flawlessly works. Basically these operations:

false ^ -1 > 0 
false ^ 1 > 0
true ^ -1 > 0
true ^ 1 > 0

Act like a valid logical XOR:

     | ^
-----+--
 F F | F
 F T | T
 T F | T
 T T | F

Could anybody please explain what happens under the hood?

Boann
  • 48,794
  • 16
  • 117
  • 146
Pavel
  • 323
  • 4
  • 11

4 Answers4

78

It's simple: > has higher precedence than ^, so

if (true ^ 1 > 0) {

is equivalent to

if (true ^ (1 > 0)) {

which is equivalent to

if (true ^ true)

... which is just logical XOR.

I would never write code like this, mind you. I would be surprised to see an example which couldn't be written more clearly in a different way.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    I never got why safety oriented languages like Java and C# even allow such code, instead of requiring parentheses for clarity. After all, there is no rule that operator precedence must be a total order. – CodesInChaos Jan 25 '17 at 16:33
  • 2
    @CodesInChaos: Well predence + associativity make the behaviour well-defined for any expression. I'm not sure whether that's what you mean by "total order" though... – Jon Skeet Jan 25 '17 at 16:51
  • 3
    @CodesInChaos I think the answer is that the are 'safety' oriented and not 'clarity' oriented. These are related but distinct. Safety requires that there be no ambiguity and this is definitely unambiguous. The idea of a clarity-oriented language is interesting though. I've never worked with something that restricted syntax _purely_ because it might be hard to understand. It is sort of odd since clarity is widely considered to be such a fundamental aspect of good development. – JimmyJames Jan 25 '17 at 17:29
  • 3
    @JonSkeet: I believe what CodesInChaos means by "total order" is that Java need not define either `^` or `>` as having higher precedence. The language could be defined such that using both in the same expression, without parentheses, would be a parse error. For instance, Haskell allows defining operators in this way: it would say "Precedence parsing error: cannot mix ‘^’ [infix 5] and ‘>’ [infix 5] in the same infix expression." – wchargin Jan 25 '17 at 20:44
  • @wchargin: Ah, I see - no rule of language design. Yes, I agree with that. That doesn't mean that total order *is* necessarily a bad thing. – Jon Skeet Jan 25 '17 at 21:13
  • @JonSkeet I just wanna see what your points look like once you hit 1 million!! LOL +1 It's 925K now so will it be 1m when you get to that point or what. – Bitcoin Murderous Maniac Feb 03 '17 at 04:54
11

Because operation > has higher priority than ^, so it is equivalent to true ^ (1>0) which is operating with same types (boolean ^ boolean).

user207421
  • 305,947
  • 44
  • 307
  • 483
Andremoniy
  • 34,031
  • 20
  • 135
  • 241
10

1 is of type int.

1 > 0 is of type boolean.

^ means XOR; and you can't XOR boolean and int.

In other words: the first expression "1" evaluates to a number; the second expression "1> 0" evaluates to boolean logic. The reason behind that is the operator predecence.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
3

Because order (priority) of operations is important, > has higher priority than ^

Here, first we check 1 > 0 and then first operation is XORed (^) with first result

Is equivalent to if(true ^ (1 > 0 ))

But, of course You can't XORed boolean with int

MatWdo
  • 1,610
  • 1
  • 13
  • 26