Reputation: 4092
I have this very simple piece of code in java:
anyMoreDelayedExplosion |= performEffect(getPanelMap(), getGameState(), this, x, y, effect, true);
anyMoreDelayedExplosion is a boolean field of the class that contains this statement. performEffect is a static method that returns either true or false.
Now, I debugged this (with Android-studio debugger), and I made sure that before executing the =| operation, anyMoreDelayedExplosion is "true". Then, after the operation, it becomes "false".
If I change the code to:
boolean res = performEffect(getPanelMap(), getGameState(), this, x, y, effect, true);
anyMoreDelayedExplosion |= res;
And check again, it correctly stays "true".
How is this possible?
My guesses:
If anyone has any guess or ideas about how to isolate this kind of behavior, I would be happy to hear them out. Thanks.
EDIT: Here are the declarations, for type completeness:
boolean anyMoreDelayedExplosion;
public static boolean performEffect(PanelMap pm, GameState state, GameSceneHittable scene, int x, int y, SpecialEffect effect, boolean playFX)
Upvotes: 4
Views: 301
Reputation: 23908
It's an issue with side effects inside the method you're calling interacting with when you observe the field and when the |=
operator "observes" the field.
In Java, the compound assignment operators like |=
store the value of the left hand side of the expression before evaluating the right hand side. So, if the method called in the RHS of the expression alter the value of anyMoreDelayedExplosion
, and they might, since you're passing this
to it, those changes will not affect the result of the |=
operation. And if you're observing that field value in the debugger after the side effect takes place, what you're seeing as the field is not what was used for the LHS input of the |=
operation.
So in this case, anyMore
is actually false at the time of the original method invocation, it gets set to true
via a side effect inside performEffect
, you're observing it in the debugger after that side effect happens but before assignment, and |=
is using the old stored false
value when it does the combination. Splitting them in to two lines causes it to evaluate the LHS using its state after performEffect
has run (and set anyMore
to true
by side-effect) but before the assignment takes place.
You need to make sure to observe the state of anyMoreDelayedExplosion
before the performEffect
method is called at all, not just before it returns, for your view to be consistent with what the code is actually doing. Adding a logging or printf statement just before the call would be a good way to do this, or just being careful about when you look at that field value in the debugger.
Section 15.26.2 of the JLS describes the compound assignment operator behavior in detail: http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.26.2
Upvotes: 4
Reputation: 882686
First things first, a pragmatic approach is probably the best.
If you have a workaround for the problem, use it. It's a worry that it happened in the first place but there should be two parallel streams happening here.
The first is to deliver your code. If the workaround works (and it does, otherwise it's not a workaround), keep it in your code (with a comment) so that you can continue.
The other stream is investigative in nature. What you describe should not be happening, sans some external forces like threading or debugger issue as you posit, or the function itself changing the flag as a side-effect of its operation.
Your best bet is to narrow it down to the bare minimum of code that has the problem, and ship that off to Google for analysis (or post the complete sample here so we can do a proper analysis rather than (educated) guesswork).
If you want to continue investigating the problem rather than shipping it off to those who might be in a better position, I'd start by single-stepping into the performEffect()
method to see what it does in detail. It may be that it's setting the boolean value itself or returning false under some circumstances. If that doesn't reveal anything, investigation of the byte-code would be my next option.
But, that's getting deep into something that you really shouldn't be worried about, especially if there's a viable workaround.
Upvotes: 1
Reputation: 5568
There's no logical explanation for the behavior you're describing. Surely the runtime behavior is correct, regardless of what you're seeing in the debugger.
If you've declared the variable anyMoreDelayedExplosion
outside an outer loop where it's repeatedly initialized and then or-equaled in an inner loop for different scenarios, I suppose it's possible you could be seeing the value after it's been re-initialized to false
. But it sounds like you know what you're doing better than to be confused by such.
Upvotes: 0