Is it possible to somehow ignore this error? I find it much easier to just put return in front of the code I don't want to run than to comment it (when the comments overlap and behave badly)...
No. It's a compile time error. So you must get rid of it before running your class.
What I usually do is put a fake if statement in front of it. Something like:
if(true)
return;
// unwanted code follows. no errors.
i++;
j++;
With this code, you will not get a Unreachable statement error. And you will get what you want.
33. if (1==1) return;
34. System.out.println("Hello world!");
It works in other languages too. But ByteCode without row 34.
It isn't possible to ignore this error since it is an error according to the Java Language Specification.
You might also want to look at this post: Unreachable code error vs. dead code warning in Java under Eclipse?
If you want disable/enable certain piece of code many times trick from old C may help you:
some_code();
more_code();
// */
/*
some_code();
more_code();
// */
Now you need only to write /* at the beginning
you have to fix that unreachable code.
public void display(){
return; //move the return statement to appropriate place
int i;
}
compiler will not compile your source code.
you have to take care of your source code that every line is reachable to compiler.
Related
This question already has answers here:
Why does Java have an "unreachable statement" compiler error?
(8 answers)
Closed 6 years ago.
The following code gives an unreachable statement compiler error
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
Sometimes for testing purposes a want to prevent a method from being called, so a quick way to do it (instead of commenting it out everywhere it's used) is to return immediately from the method so that the method does nothing. What I then always do to get arround the compiler error is this
public static void main(String[] args) {
if (true) {
return;
}
System.out.println("unreachable");
}
I'm just curious, why is it a compiler error?? Will it break the Java bytecode somehow, is it to protect the programmer or is it something else?
Also (and this to me is more interesting), if compiling java to bytecode does any kind of optimization (or even if it doesn't) then why won't it detect the blatant unreachable code in the second example? What would the compiler pseudo code be for checking if a statement is unreachable?
Unreachable code is meaningless, so the compile-time error is helpful. The reason why it won’t be detected at the second example is, like you expect, for testing / debugging purposes. It’s explained in The Specification:
if (false) { x=3; }
does not result in a compile-time error. An optimizing compiler may
realize that the statement x=3; will never be executed and may choose
to omit the code for that statement from the generated class file, but
the statement x=3; is not regarded as "unreachable" in the technical
sense specified here.
The rationale for this differing treatment is to allow programmers to
define "flag variables" such as:
static final boolean DEBUG = false;
and then write code such as:
if (DEBUG) { x=3; }
The idea is that it should be possible to change the value of DEBUG
from false to true or from true to false and then compile the code
correctly with no other changes to the program text.
Reference: http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
Its because the compiler writer assumed that the human at the controls is dumb, and probably didn't mean to add code that would never be executed - so by throwing an error, it attempts to prevent you from inadvertently creating a code path that cannot be executed - instead forcing you to make a decision about it (even though, as you have proven, you still can work around it).
This error is mainly there to prevent programmer errors (a swap of 2 lines or more). In the second snippet, you make it clear that you don't care about the system.out.println().
Will it break the Java bytecode somehow, is it to protect the programmer or is it something else?
This is not required as far as Java/JVM is concerned. The sole purpose of this compilation error is to avoid silly programmer mistakes. Consider the following JavaScript code:
function f() {
return
{
answer: 42
}
}
This function returns undefined as the JavaScript engine adds semicolon at the end of the line and ignores dead-code (as it thinks). Java compiler is more clever and when it discoveres you are doing something clearly and obviously wrong, it won't let you do this. There is no way on earth you intended to have dead-code. This somehow fits into the Java premise of being a safe language.
http://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.21
says:
14.21. Unreachable Statements
It is a compile-time error if a statement cannot be executed because it is unreachable.
Example 1:
In this case you are return before any statement because of it compiler never going to execute that code.
public static void main(String[] args) {
return;
System.out.println("unreachable");
}
In second code I have put the statement above of return and its work now :)
Example 2:
public static void main(String[] args) {
System.out.println("unreachable"); // Put the statement before return
return;
}
The reason behind this is that if you return sometime then code after it never going to execute because you already return the function data and as so it is shown unreachable code.
It's because it's a waste of resources for it to even be there. Also, the compiler designers don't want to assume what they can strip out, but would rather force you to remove either the code that makes it unreachable or the unreachable code itself. They don't know what is supposed to be there. There's a difference between the optimizations where they tweak your code to be a bit more efficient when it's compiled down to machine code and blatantly just removing code "you didn't need."
This is actually not a problem for solving but I felt curious that why the following code would gives the confusing indentation warning for possible missing of surrounding block:
if(x!=y)
System.out.println("not equal");
index++;
If I put the System.out.println("not equal"); inside {} the warning would go away but I feel curious in what situation the current looking code would go wrong.
The problem is that, when you read this code, you are missing a visual cue that the System.out.println("not equal"); is only run when the condition (x!=y) is true. The error will go away as well when you indent the code:
if (x != y)
System.out.println("not equal");
Some people may still advise against using single-line consequences and encourage you to use blocks anyway. People might be tempted to just add another line of code underneath the System.out, thinking that it will also just be executed when x != y - without noticing that the braces are missing.
Anything within an if statement is generally indented for clarity. For instance:
if(foo) {
if (bar) {
System.out.println("foo bar");
}
}
As you are writing only a 1 line statement, you don't need the {} but indentation is still recommended. Without it, it is not immediately obvious what will and won't get executed.
For instance, if someone reading your code didn't know that only 1 line get's executed in an if statement with no brackets, they might think the index++; line will only get called if (x!=y)
Also, you are more likely to make mistakes as a developer if you don't use {} for all if statements. If you get into the habit of not using them, and you forget to use them for a multi-line if statement, you will get unexpected results. For instance, if you decided to put something after the System.out.println("not equal"); within the if block, it would be very easy to forget the {}.
I extracted someone's APK (Android app) to see the Java source code and saw a lot of return; code, even on void methods.
For example:
public void doSomething(){
do{
return; //This line makes the code below unreachable and can't compile in Eclipse
switch(num){
...
default:
return;
}
}while(...)
...
}
How come the app seems to run well on my phone?
I guess return; is like a shortcut to break from the method. Is that right?
If the method returns void then return; just exits out of the method at that statement, not running the following statements.
Yes, that is correct. Look at the bottom of http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html:
The return Statement
The last of the branching statements is the return statement. The
return statement exits from the current method, and control flow
returns to where the method was invoked. The return statement has two
forms: one that returns a value, and one that doesn't. To return a
value, simply put the value (or an expression that calculates the
value) after the return keyword.
return ++count; The data type of the returned value must match the
type of the method's declared return value. When a method is declared
void, use the form of return that doesn't return a value.
return;
To answer your first question: I assume this code is decompiled. Note that decompilers are not one to one converters of binary dex code to whatever Java code has been used to generate these binaries. They often have problems with parsing different control structures like loops and switches. Besides, the binary may be obfuscated, meaning that after compilation the binary is modified in a way to be fully operational, but harder to decompile and reverse engineer (basically to prevent what you're trying to do here :) ). They can add dead code, like return statement that shouldn't be there, mangle loops and if statements to confuse decompiled code, etc.
return keyword is used basically in a void method ,it helps to break the conditional statement to come out of method.
I am replacing a old C++ code with Java:I know there is no equivalent of goto in java as it causes many surprising errors and unintended loop terminations.
C++ code: //I have skipped the actual code
for(//some condition){
if (excl(grds[i],0))
{
//do something
goto breakout;
}
//some more code
breakout:
//rest of the code
}//end of for loop
Java representation:
for(//some condition){
if (excl(grds[i],0))
{
//do something
}
else
{
//some more code
}
//rest of the code
}//end of for loop
I have kept the "some more code" part in the else section so I guess it will function same as the breakout. When the if condition is true it wont go to the else part and rest of the code will be executed as usual. I guess break or continue wont serve the purpose as we need to any way run the rest of the code section for all iterations.
Is this the correct way of representing this C++ code in Java?
Yes, that would be the better way — in Java, and in C++.
This is probably the easiest way:
for(//some condition){
if(!excl(grds[i],0))
{
//some more code
}
//rest of the code
}//end of for loop
You really shouldn't be using goto in C++. As a side note, in Java you can have named blocks that can be used to simulate a goto:
namedBlock:
{
// some code
if(condition)
break namedBlock;
// some more code
}
// rest of the code
But this is awful practice. Don't do it. Forget I even mentioned it ;)
for(//some condition){
if (!(excl(grds[i],0)))
{
//some more code
}
//rest of the code
}//end of for loop
Edit: after your clarification, the way you did it is fine.
Why can't you have it like this?
In your C++ code, //some more code is only executed when the condition is false and the //rest is always executed. So put that in the if.
Yes.
To be more precise, that's the correct best way of representing that code in C++ as well. Why use goto instead of a simple if?
This is a hack
for(//some condition){
do { // note this *do*
if (excl(grds[i],0))
{
break; // out of do/while
}
//some more code
}
while(false); // do only once
//rest of the code
}//end of for loop
I'm sure people will hate me for this, but you can get closer to the goto statement in Java than the if/else example. For instance, you can do:
for(/*some condition*/){
breakout: {
if (excl(grds[i],0)) {
break breakout; //this will jump to the end of the "breakout" block
}
//some more code
}
//rest of the code
}
Of course, this is not an example of good Java coding style, and just because this can be done doesn't mean it should be done. Really you should stick with the if/else.
There are occasions, very rare occasions, when using goto is exactly the right choice in C++. The example shown is not one of them. This is a goto that should never have been used, period. A goto has zero reason for existence if you can eliminate the goto with no additional variables, no increase in the complexity.
Some valid uses of goto in C++ can be easily eliminated in Java.
C and C++ do not have a way to break or continue out of a nested loop. Java does. When the target of a goto is immediately before some close brace, change the goto label with continue label. When the target of a goto is immediately after some close brace, change the goto label with break label. (The label statement may need to be moved around.)
Some C++ code uses goto in lieu of throw for local error handling / local error recovery. C++ exceptions have a pretty stiff performance penalty. If the code is being converting to Java it's kinda obvious that performance is not an issue. Use Java exceptions for this kind of goto.
I'd like a mechanism to throw a compile-time warning manually. I'm using it to flag unfinished code so I can't possibly forget about it later. #Deprecated is close but warns at caller site, not at creation site. I'm using eclipse. Something like #Warning in C#.
Why not just add a flag in the source code like //TODO: or something? And then just search for all occurances of TODO in the file? You could even have some special flag too like FINISHME or something.
If you have hundreds of TODOs in your project from the team, you can filter by a string e.g. your initials in the Task pane's top-right menus.
A lot better than using the deprecated annotation in my humble opinion the suppresswarnings annotation.
#SuppressWarnings("XXX")
can be annotated almost everywhere and as long as XXX is not a valid warning you will get a warning from eclipse about that.
Create an annotation that prints out a warning.
You could try to throw an exception if an unfinished method is called (e.g.)
throw new UnsupportedOperationException()
(Or you could create your own Exception). Obviously this will only help at runtime (unless you do a search or something in your code for it - but Todo would be a better solution for that)
And if you are using eclipse you can mark your unfinished code with // TODO and it will show up on your task list (and the right gutter if you have it configured). Obviously things can get very noisy if you have a lot of Todo tags.
I do this all the time by just putting "*** LEFT OFF HERE ***" or some such. As this is not valid Java or C++ or pretty much any other language syntax, the compiler gives an error message for it.
Of course that gives an error and not a warning. If you want to otherwise successfully compile, I suppose an easy thing to do would be to put a statement that you know will generate a compiler warning with a comment saying "finish this" or whatever.
When I want to warn users about calling a method, I (mis)use the build-in #Deprecated annotation which generates a warning at the caller side. Actually it has a slightly different meaning, but I don't care.
/** [Additional information...]
* It is marked as deprecated to warn callers. */
#Deprecated public void methodForWhichIWantToCreateAWarning();
I'm not sure if there is anything like that in java
but here is something that may help you:
compile the code below like this:
javac -Xprint verbose.java
public class verbose{
public #interface SomeMessage {
String somevalue();
}
#SomeMessage(
somevalue = "WHOOOOHOOOO000000000000000"
)
public static void main(){
System.out.println("Hello");
}
}