SF/JavaOne, Day 2, JavaGotchas


Just got out of the Java-Gotchas talk being held by Google Engineers
Josh Bloch and Neal Gafter.  It was a whole bunch of fun, and i
have to admit that even with my extensive java knowledge i was thrown
by several of the questions.  For those who don’t know, this
seminary (also pionered by Eric Gunnerson) is about presenting very
simple code sample to the audience that very often do not do what you’d
expect it to do.  The audience then votes on a set of possible
answers and then the presenters reveal which is the right answer and
give a “moral” that developers can abide by to help create the clearest
code possible.



Afterwards though i ended asking myself “why did you think that the
code would behave differently than it actually would?”  And i
started thinking about how the code would behave in C# and i realized
that it would in fact be different and would end up behaving far more
intuitively than they would in java.  I ended up coding these up
to be sure, and… yup… in the end, more than half of the problems
end up behaving as one would expect in C#.



The ones that behave weirdly in both C# and Java are worth taking a
look at.  For example, this one threw me completely off:


public class AnimalFarm
{
static void main(String[] args)
{
final String pig = "length: 10";
final String dog = "length: " + pig.length();

System.out.println("Animals are equal: " + pig == dog);
}
}



The question was: What will the above code print when run.  The possible answers were:

  1. “Animals are equal: true”
  2. “Animals are equal: false”
  3. It depends (perhaps on compiler or VM)
  4. None of the above.

So i’m sitting there, (all arrogant like), saying: “well, in C# it
would print ‘Animals are equal: true’ as you’d expect, and in java it will be at best ‘2’ and at worse ‘3’ depending on
whether or not the compiler/runtime is willing to intern values which it can statically determine with flow analysis”.



What did you think the answer what?  Think about it a bit, then scroll down.

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

|

Think you’ve got it?  Well, the answer is “D: None of the
above”.  Why?  Because precedence rules dictate that the
above statement will actually get parsed as:

("Animals are equal: " + pig) == dog

Which would then ask the question: Is “Animals are equal: length: 10” equal to “length:
10”?  And no matter if it’s doing reference or value equality, the
answer is always “false” and so both languages will print out “false”
to the console.



That was some egg on my face, and it got me thinking that maybe it
would be appropriate to have tools in place to help warn users about
these sorts of mistakes they might be making since it’s possible it’s
not what they intended.  Tough to tell, but worth giving some
though to.


Comments (18)

  1. Matt says:

    That addition struck me as odd… I always add extra parens just to make clear what I’m doing.

  2. tzagotta says:

    Why is that order of ops confusing? If the expresion was "2 + 3 == 7" it would be clear, right? The operator precedence doesn’t depend on the data types.

  3. evolve says:

    "it would be appropriate to have tools in place to help warn users about these sorts of mistakes they might be making since it’s possible it’s not what they intended"

    i would imagine that it’s not so hard to parse the expression:

    ("Animals are equal: " + pig == dog)

    in real time, and then insert extra "blinking" parens to warn user like this:

    (("Animals are equal: " + pig) == dog)

    [you know, the same way Intellisense automatically makes the matching parens highlighted when you close a paren within an expression.]

  4. evolve says:

    i meant, the same visual way Intellisense automatically makes…

    since the mechanism to accomplish each of those goals are different.

    but i thought that if the cplr knows how to parse an expression, then Intellisense can just have the same code to parse it in real time. right? knowing where to insert the blinking parens wouldn’t be so hard, man. and then when u hover the mouse on the warning squiggle, the tooltip should display "Did you mean ("Animals are equal: " + (pig == dog)) instead?" Or, display a list of possible parens placing if there are multiple groupings.

  5. Roman says:

    Interestingly enough, I’ve come across an related problem with .Net’s handling of "flagged" enumerations.

    Assume you have an bitflagged enumeration called

    "Item" with:

    Food = 1

    Apple = 3 (apple | food)

    Bear = 4 (just a bear,and not food)

    Candy = 9 (candy | food)

    CandyApple = 11 (apple | candy | food)

    When I do the following test :

    Item possiblyFood = CandyApple

    If (PossiblyFood & Apple == Apple) { EatIt() }

    the compiler tells me off for performing a bitwise operation on a boolean and will not let me proceed. I’m forced to set explicit precedence:

    If ((PossiblyFood & Apple) == Apple) { EatIt() }

    this now works as I intended. I thank the compiler and continue with my work.

    In the concatenation example derived from Java, the similar omission of explicit precedence doesn’t prevent compilation. I’m not sure how the intellisense operator could identify an implicit need to precede one operation with another. A developer might very well want to concatenate before comparison, which is perfectly legal but otherwise impossible to decipher implicitly.

    Suggesting multiple groupings would be a possible solution, but if you’ve got half a dozen different operations of varying types in an expression without any explicit precedence, you would end up with an unwieldy number of variations that the compiler would have to suggest.

    A simpler solution than having the compiler suggest an unknown number of variations would be to give a compiler warning when precedence is not clearly defined. In the concatenation example above it is not clearly defined, because string concatenation has no relation to boolean comparions. And neither of these have any useful relation to bitwise operations, so any precedence is arbitrary, even based on sequence. I don’t think we can convince all developers to simply remember not to rely on implicit precedence.

    In a mathematical formula, brackets can be removed predictably by changing around the formula to have implicit precedence match what is expected. In computing, the ability to modify expressions while executing them renders this implicit precedence potentially hazardous.

    As a side note, i put all my example code in VB.NET and got identical results, right down to the compiler errors and incorrect results.

  6. CyrusN says:

    Tzagotta: " Why is that order of ops confusing? "

    I don’t know. But it is. Hence the "gotcha" :)

    Humans aren’t compilers, and we often bring in our own interpretations that middy the actual meaning of the code.

    if we didn’t do this, there would be no need for warnings, or making people aware of these potential problems.

  7. CyrusN says:

    Evolve/Roman: Very interesting ideas. I’ll have to give them some more though.

    BTW: one of the problems is that with a sufficently complex expression you can get a huge number of possible interpretations. Providing UI to help with that can be… difficult :)

  8. Darren Oakey says:

    I always get amused when I’m in an interview (on either side of the table ;)… because if there are example questions, someone always comes up with some silly question about operator precedence.

    And I barely know, and really don’t care – and don’t care if the interviewer does either.

    Because I would get very upset at any of my programmers who did this – even though it’s completely valid:

    > if (a == b && c == d)

    Because, like we are always saying – coding is about readability… and really – this:

    > if ((a==b) && (c==d))

    is both cleaner and safer – especially as we have so many languages to deal with these days – all with their own precedence rules.

    I think at any point relying on operator precedence is a mark of a poor programmer.

  9. Patric J says:

    Good example, got me as well

  10. evolve says:

    "BTW: one of the problems is that with a sufficently complex expression you can get a huge number of possible interpretations. Providing UI to help with that can be… difficult :) "

    well, a simpler solution would be just display the result of that expression when u hover the squiggle

  11. ericgu says:

    Dude,

    Two comments:

    1) I think you mean seminar, not seminary

    2) I don’t think I really pioneered it, though I love doing it.

    3) I went to Josh and Neal’s presentation last year, and they did a masterful job.

  12. ff says:

    [url=http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>http://www.88tm.com/“>