Java methods - what RETURN actually means? - java

I'm pretty certain I'm missing something really obvious here but this seems quite bizarre.
I'm developing for Android using Eclipse - and I have a method similar to which I'm debugging and it's doing something rather odd...
public boolean test() {
if (variable == value)
return true;
// more code appears here
return false;
}
Stepping through that, on the first line (the if statement) the debugger suggests that variable does indeed equal value (they've both byte variables with a value of 0) - the debugger then moves onto the 2nd line (the return true) but it then moves on to the last line (return false) - skipping everything inbetween!?
The value returned was 'false'
WTF is going on there? I'd assumed that RETURN would exit the method entirely - but the debugger (and the return value being sent back - being false) suggests that it does nothing of the sort!?
What am I missing which is staring me in the face? Are return statements as the last line of methods always executed or something?
p.s. interesting update...
The variables I'm using are assigned in code which I didn't write - I just dug-out the source and re-built/re-ran the debugger with access to that source and I found this line in it
byte variable = (byte)9;
Can you see anything wrong with that and would that perhaps explain the problem do you think!? I've emailed the author but meanwhile - erm....
Update2
OK, I've completely remade the project, cleaned and rebuilt it, uninstalled and reinstalled it into the phone and the debugger now behaves more sensibly...
The problem is clearly the use of '9' (they use 0-9 as possible values in a byte!!) - what's happened now is that although the debugger is suggesting 'variable' is "0" - it's also failing comparison to (byte)0 and thus I get a 'false' return - which is actually correct.
I'm obviously stuck until they change their code to use a short - as for accepting an answer, it's tricky as the 'rebuild everything' answers and the 'compare using (byte) or bytevalue()' answers were sort-of both right!?

If they are Byte objects allocated with new, then == will test if they are the same object in memory and return false. Try to use:
variable.byteValue() == value.byteValue()
instead.

I think your problem is that, when you use the Byte object, doing the == is not comparing the VALUES of the bytes, but is instead comparing the object in memory. This is similar to how String works.
Instead, try:
public boolean test() {
if (variable.equals(value))
return true;
// more code appears here
return false;
}
Update based on Comment
If you are comparing two bytes (particularly a variable and a value), make sure you are casting to a byte on both values (see Binary Numeric Promotion as to why). So, try:
public boolean test() {
if ((byte)variable == (byte)value)
return true;
// more code appears here
return false;
}

I don't think your code buffer in eclipse is matching what is being debugged. The only time you should see code execute past a return statement is of you are using a finally block, in which you will see the code execute in the finally block after the return statement in the debugger.

Are return statements as the last line of methods always executed or
something?
No.
Try surrounding your if block in {} and then see what happens.

Your description of your code does not match the code you pasted. I suspect that this is a symptom of the real problem: you are stepping through source code that is not the same as your compiled code. The line numbers don't match. So it looks like it's doing all kinds of wacky things. Rebuild your compiled code and debug again.

Logically, a return statement does immediately exit a method--
But before it does, other things might happen, like a finally statement after an enclosing try block.
Usually, the debugger will skip to the closing brace of a method after the return statement, rather than to the last return statement.
This makes me think there is something unusual with your method, or that the method you are seeing in the debugger is not identical to the method that is running on the device.

It shouldn't be doing it and what you know about return already is correct.
This could happen when the compiled binary is different than the source code. Try cleaning your project and rebuilding it.

You could try remove "more code appears here" and add this code line-by-line, until you find mistake. Also try restart eclipse, clean up project and redeploy application.

This behavior is normal using the Eclipse debugger. I recommend you to watch the value returned by the method itself and not the code being executed (it will be true, not false).
For example, try the following code. You will see that return true is reached, but later foo, and foo2 are not initialized (although it seems to reach return false).
public boolean test() {
if (variable == value)
return true;
int foo = 5;
int foo2 = 7;
// more code appears here
return false; }

I don't see an open bracket after your "if" statement. It should look like this:
public boolean test() {
if (variable == value) {
return true;
// more code appears here
}
return false;
}
With the additional brackets the "true" will only be associated with the IF conditions, and the false will be only if the IF conditions are not satisfied.

Related

Java boolean method: unreachable statement

I want to check if there are no elements in an array.
private Player[] players = new Player[maxPlayers];
public boolean activePlayer(){
for(int i = 0; i < players.length; i++){
if(players[i] != null) {
return true;
break;
}
}
return false;
}
ItelliJ marks break; red with the message unreachable statement. What does this mean and how can I fix this?
The return statement right before the break will immediately end the method, so the break will never be reached.
in simple terms, the if the first if condition is true then it will only goto "return true;" and exit... if it does not go into the If block then it will continue to loop through and end at "return false;" So yes intelliJ is right. it should never come to the "break;"
the return true; will actually do the break for you and you don't need to do it explicitly and it will return to where ever you are calling the function "activePlayers()"
If you explain why you are adding a break, we may be able to help you further
Think through the serial behavior of the program, one line at a time. If it makes it past the conditional statements, it will hit the return statement. In Java, return terminates a function, returning control to the calling function and potentially returning a value as well. The break line will never be touched!
This might help you understand the flow of control in a Java program: http://www.dickbaldwin.com/java/Java026.htm
If you add more information about what you would like the program to do/ what you expect from the break statement, we'd be happy to help!
We use return to return a value back to the calling method, so therefore once control goes inside the if block the value true is returned to the calling method hence the break will never be reached.
To put it simply, return ends the execution of the current method and returns a value back to the caller.
Well, in Java, returning a value in a function will, in order,:
1. stop executing the code inside of the function
2. return the value in the function
ItelliJ is a very snappy and "intelligent" code checker that tells you when something is wrong or buggy.
It is giving you the error, "unreachable statement" because the "break" statement never gets executed because when you return "true"... (look back at the first part of the answer)... the break statement never gets executed.
So it is therefore an "unreachable" statement that will never be executed in any case whatsoever.

Debugger shows "malformed expression" for a .length called on a method that returns boolean[]?

This isn't a code problem, more of a need for an explanation.
I have a function that is overridden and creates a boolean array, as in:
#Override
protected boolean[] fillSort()
{
boolean[] vbSort = new boolean [14];
//Do something on elements
return vbSort;
}
Later on, in the base file I want to get length of that array, I invoke the overridden method and compare it, as in:
if (fillSort().length == xyz.length)
It works correctly, however if I want to check the returned length through the debugger, it shows me that fillSort().length is a malformed expression and is equal to error.
If I put it on the watchlist, it returns the length of the base (not overridden) method. Why?
The correct length is there, the program proceeds correctly, but the debugger doesn't see it. How so?
EDIT: Using Netbeans 8.2 as IDE.
The Netbeans debugger is not clever enough to evaluate fillSort() when you hover over it.
That's why it appears to be a malformed expression.
In some way it's helping you: The fact that you are "Doing something on elements" is not relevant to the return length. Perhaps you ought not not be relying on an anonymous temporary but using something like
boolean[] foo = fillSort();
if (foo.length == xyz.length)

Eclipse flags a piece of code with a 'Dead code' warning. Why in this case?

I know that there are a few examples of 'random dead code warning' in Eclipse.
But specifically for my case, I want to find out whether this is also a 'false positive' or whether I am too tired to understand what is going on...
#Override
public int getNumUnappendedCol() {
return appendIndex == -1 ? getNumCol() : appendIndex;
}
This ternary statement is being flagged, specifically the condition and appendIndex. As I understand it (not my code), this is supposed to return appendIndex if it is not equal to -1. Otherwise return the value obtained from getNumCol().
Am I missing something or should I just ignore Eclipse? I regularly refresh/ clean/ build the project so that wouldn't solve the issue.
The problem ended up being a final declaration of appendIndex which was initialized to -1, so the ternary statement could never even access the false option.

Does Java compiler understand two returns?

Is it safe to write something like this in java?
if(var==2){
return true;
}
return false;
Somehow, while debugging, the compiler executes the first return, and goes to the second.
Shouldnt the method be terminated after the first return?
Yes, it's safe.
But consider writing this instead:
return (var==2);
That's perfectly safe. Alternatives are return var == 2; or return var == 2 ? true : false;
It's perfectly safe and valid Java code. And it's not possible for the return to not actually return.
If you believe it is, I suggest you do a clean and then recompile, it's possible there is a mismatch between the compiled class and your source code.
Yes it is safe! You can have as many returns as you want - the method will be terminated after the first one
Yes it's perfectly fine to do that, even though you can write it shorter than that. Perhaps it just looks like it's getting to your second return while you're visually stepping through your code, when var == 2, but it's stepping to the end of the function. You should be able to check the return value of the function after it's finished executing.
If you really wanted to be sure, you could use assert statements or even a print statement with the return value.

Can't breakpoint the last statement of a code block in Eclipse

if (true) {
String a = "foo";
String b = "bar";
}
If I set a breakpoint at String a = "foo"; eclipse will stop, and I can step over and see the value of a inside the variables window. But I can't step over the 2nd statement, it just leaves the code block and I never see the value of b.
This forces me to add a noop statement after String b = "bar"; just so I can see what b contains. I also can't add a breakpoint on the closing } which I think are maybe related issues.
I know Visual Studio allows this, so is there a way to do this in Eclipse?
To set a breakpoint at the end of an arbitrary block is not possible (without byte-code hacking).
If it is a method body, then it is possible: you can set a Method breakpoint. Do this by double-clicking on the method definition line:
(notice the little arrow?) and then in the breakpoints view, select the breakpoint to see both an Entry and an Exit option tick-box in the displayed properties:
The little arrow indicates that, by default, we have set a breakpoint on entry to the method.
Now select Exit (and deselect Entry) and you will see this in the breakpoints view:
(There is a different little arrow, indicating an exit breakpoint.)
Now run the debugger on this little breaker ('Debug As a Java Application') and it will stop on the exit brace of the method:
and the local variables (only a in this case) are now visible (with the correct values) in the Variables view:
It is worth noticing that this type of breakpoint traps method exit however this happens -- even, for example, if we exit by throwing an exception.
You can highlight the expression on the right hand side of the assignment and press Ctrl+Shift+I (for 'inspect' I think). It will evaluate the expression and give you the result. That way you can know the value of b without needing a breakpoint after the assignment.
I'm honestly not sure what's going on in your Eclipse installation. I'm working in Java and just tried everything I can think of. I checked a static method for breakpoint on the last line that is not a } and it works just fine. I checked the same for a non-static method.
It breaks down this way: you can't breakpoint on a curly brace end, but it will default to whatever is under the curly brace, line-wise. So if you have a nested function:
public int DoesStuff(int x, int y) {
if(x > y) {
DoThing;
}
else {
DoOtherThing;
}
}
Then the last two braces cannot be break-pointed, but DoThing and DoOtherThing can. Make sense?
If ending statement is assignment and it is on local variable why do you want to see its value because it will not be in scope anymore and can't effect.
If it's setting same class attribute then you can see it when you return from this call and you have the object on which this method operated.
Although this doesn't answer the question but I am trying to understand the use-case of your problem.

Categories