This is a code snippet I found in an open source Java templating project.
Does anyone have a clue what this construct may be good for?
final public Expression Expression() throws ParseException {
Expression exp;
exp = OrExpression();
{if (true) return exp;}
throw new Error("Missing return statement in function");
}
This is sloppy code. The actual effect is simply return OrExpression();.
There is one excuse that I accept for code like this: There are lots of other methods like it, which follow a similar pattern but are more complex such that the useless bits here are not useless. This is a bit of an extreme example, however.
However, there is almost no excuse for the throw new Error("Missing return statement in function");. The Java compiler will refuse to compile a method whose return type is not void and which has a code path which reaches the end (does not return, throw, or enter an infinite loop). The only reason this would be a good idea is if the intent was to permit incomplete code to compile — i.e. fail at run time rather than compile time so that other parts of the code can be used or tested — but even then applying it to all methods is a bad idea.
This is an automatically generated code from JavaCC.
Related
public Void traverseQuickestRoute(){ // Void return-type from interface
findShortCutThroughWoods()
.map(WoodsShortCut::getTerrainDifficulty)
.ifPresent(this::walkThroughForestPath) // return in this case
if(isBikePresent()){
return cycleQuickestRoute()
}
....
}
Is there a way to exit the method at the ifPresent?
In case it is not possible, for other people with similar use-cases: I see two alternatives
Optional<MappedRoute> woodsShortCut = findShortCutThroughWoods();
if(woodsShortCut.isPresent()){
TerrainDifficulty terrainDifficulty = woodsShortCut.get().getTerrainDifficulty();
return walkThroughForrestPath(terrainDifficulty);
}
This feels more ugly than it needs to be and combines if/else with functional programming.
A chain of orElseGet(...) throughout the method does not look as nice, but is also a possibility.
return is a control statement. Neither lambdas (arrow notation), nor method refs (WoodsShortcut::getTerrainDifficulty) support the idea of control statements that move control to outside of themselves.
Thus, the answer is a rather trivial: Nope.
You have to think of the stream 'pipeline' as the thing you're working on. So, the question could be said differently: Can I instead change this code so that I can modify how this one pipeline operation works (everything starting at findShortCut() to the semicolon at the end of all the method invokes you do on the stream/optional), and then make this one pipeline operation the whole method.
Thus, the answer is: orElseGet is probably it.
Disappointing, perhaps. 'functional' does not strike me as the right answer here. The problem is, there are things for/if/while loops can do that 'functional' cannot do. So, if you are faced with a problem that is simpler to tackle using 'a thing that for/if/while is good at but functional is bad at', then it is probably a better plan to just use for/if/while then.
One of the core things lambdas can't do are about the transparencies. Lambdas are non-transparant in regards to these 3:
Checked exception throwing. try { list.forEach(x -> throw new IOException()); } catch (IOException e) {} isn't legal even though your human brain can trivially tell it should be fine.
(Mutable) local variables. int x = 5; list.forEach(y -> x += y); does not work. Often there are ways around this (list.mapToInt(Integer::intValue).sum() in this example), but not always.
Control flow. list.forEach(y -> {if (y < 0) return y;}); does not work.
So, keep in mind, you really have only 2 options:
Continually retrain yourself to not think in terms of such control flow. You find orElseGet 'not as nice'. I concur, but if you really want to blanket apply functional to as many places as you can possibly apply it, the whole notion of control flow out of a lambda needs not be your go-to plan, and you definitely can't keep thinking 'this code is not particularly nice because it would be simpler if I could control flow out', you're going to be depressed all day programming in this style. The day you never even think about it anymore is the day you have succeeded in retraining yourself to 'think more functional', so to speak.
Stop thinking that 'functional is always better'. Given that there are so many situations where their downsides are so significant, perhaps it is not a good idea to pre-suppose that the lambda/methodref based solution must somehow be superior. Apply what seems correct. That should often be "Actually just a plain old for loop is fine. Better than fine; it's the right, most elegant1 answer here".
[1] "This code is elegant" is, of course, a non-falsifiable statement. It's like saying "The Mona Lisa is a pretty painting". You can't make a logical argument to prove this and it is insanity to try. "This code is elegant" boils down to saying "I think it is prettier", it cannot boil down to an objective fact. That also means in team situations there's no point in debating such things. Either everybody gets to decide what 'elegant' is (hold a poll, maybe?), or you install a dictator that decrees what elegance is. If you want to fix that and have meaningful debate, the term 'elegant' needs to be defined in terms of objective, falsifiable statements. I would posit that things like:
in face of expectable future change requests, this style is easier to modify
A casual glance at code leaves a first impression. Whichever style has the property that this first impression is accurate - is better (in other words, code that confuses or misleads the casual glancer is bad). Said even more differently: Code that really needs comments to avoid confusion is worse than code that is self-evident.
this code looks familiar to a wide array of java programmers
this code consists of fewer AST nodes (the more accurate from of 'fewer lines = better')
this code has simpler semantic hierarchy (i.e. fewer indents)
Those are the kinds of things that should define 'elegance'. Under almost all of those definitions, 'an if statement' is as good or better in this specific case!
For example:
public Void traverseQuickestRoute() {
return findShortCutThroughWoods()
.map(WoodsShortCut::getTerrainDifficulty)
.map(this::walkThroughForestPath)
.orElseGet(() -> { if (isBikePresent()) { return cycleQuickestRoute(); } });
}
There is Optional#ifPresentOrElse with an extra Runnable for the else case. Since java 9.
public Void traverseQuickestRoute() { // Void return-type from interface
findShortCutThroughWoods()
.map(WoodsShortCut::getTerrainDifficulty)
.ifPresentOrElse(this::walkThroughForestPath,
this::alternative);
return null;
}
private void alternative() {
if (isBikePresent()) {
return cycleQuickestRoute()
}
...
}
I would split the method as above. Though for short code () -> { ... } might be readable.
I just randomly tried seeing if new String(); would compile and it did (because according to Oracle's Java documentation on "Expressions, Statements, and Blocks", one of the valid statement types is "object creation"),
However, new int[0]; is giving me a "not a statement" error.
What's wrong with this? Aren't I creating an array object with new int[0]?
EDIT:
To clarify this question, the following code:
class Test {
void foo() {
new int[0];
new String();
}
}
causes a compiler error on new int[0];, whereas new String(); on its own is fine. Why is one not acceptable and the other one is fine?
The reason is a somewhat overengineered spec.
The idea behind expressions not being valid statements is that they accomplish nothing whatsoever. 5 + 2; does nothing on its own. You must assign it to something, or pass it to something, otherwise why write it?
There are exceptions, however: Expressions which, on their own, will (or possibly will) have side effects. For example, whilst this is illegal:
void foo(int a) {
a + 1;
}
This is not:
void foo(int a) {
a++;
}
That is because, on its own, a++ is not completely useless, it actually changes things (a is modified by doing this). Effectively, 'ignoring the value' (you do nothing with a + 1 in that first snippet) is acceptable if the act of producing the value on its own causes other stuff to happen: After all, maybe that is what you were after all along.
For that reason, invoking methods is also a legit expressionstatement, and in fact it is quite common that you invoke methods (even ones that don't return void), ignoring the return value. For void methods it's the only legal way to invoke them, even.
Constructors are technically methods and can have side effects. It is extremely unlikely, and quite bad code style, if this method:
void doStuff() {
new Something();
}
is 'sensible' code, but it could in theory be written, bad as it may be: The constructor of the Something class may do something useful and perhaps that's all you want to do here: Make that constructor run, do the useful thing, and then take the created object and immediately toss it in the garbage. Weird, but, okay. You're the programmer.
Contrast with:
new Something[10];
This is different: The compiler knows what the array 'constructor' does. And what it does is nothing useful - it creates an object and returns a reference to the object, and that is all that happens. If you then instantly toss the reference in the garbage, then the entire operation was a complete waste of time, and surely you did not intend to do nothing useful with such a bizarre statement, so the compiler designers thought it best to just straight up disallow you from writing it.
This 'oh dear that code makes no sense therefore I shall not compile it' is very limited and mostly an obsolete aspect of the original compiler spec; it's never been updated and this is not a good way to trust that code is sensible; there's all sorts of linter tools out there that go vastly further in finding you code that just cannot be right, so if you care about that sort of thing, invest in learning those.
Nevertheless, the java 1.0 spec had this stuff baked in and there is no particularly good reason to drop this aspect of the java spec, therefore, it remains, and constructing a new array is not a valid ExpressionStatement.
As JLS §14.8 states, specifically, a ClassInstanceCreationExpression is in the list of valid expressionstatements. Click that word to link to the definition of ClassInstanceCreationExpression and you'll find that it specifically refers to invoking constructors, and not to array construction.
Thus, the JLS is specific and requires this behaviour. javac is simply following the spec.
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."
For testing purposes, I often start typing some code in an already existing project. So, my code I want to test comes before all the other code, like this:
public static void main(String[] args)
{
char a = '%';
System.out.println((int)a);
// To know where '%' is located in the ASCII table.
// But, of course, I don't want to start the whole project, so:
return;
// The real project starts here...
}
But the compiler complains about the return-statement, because of the following "dead code". (While in C++ the compiler obeys the programmer and simply compiles the return statement)
To prevent the compiler complains, I write a stupid if-statement:
if (0 != 1) return;
I hate it. Why can't the compiler do what I ask? Are there some compilation flags or annotations or whatever to solve my problem?
Thanks
There are no flags to turn of this behaviour. The rules that make dead code a compile time error are part of the JLS (§14.21 Unreachable Statements) and can't be turned off.
There's an explicit loophole in the loop which allows code like this:
if (true) return;
someOtherCode(); // this code will never execute, but the compiler will still allow it
This is done explicitly to allow "commenting-out" or conditional compilation (depending on some static final boolean flag).
In case you're curious: the loophole is based on the fact that a known-constant value of the condition expression of an if statement is not considered when checking reachability of code within or after the if statement. A similar situation occurs with while, where known-constant values are considered, so this code will not compile:
while (true) return;
someOtherCode(); // this will be flagged as an unreachable statement
You shouldn't have lots of dead cod ein your project however two ways I get around this for prototyping.
Use /* */ to comment out the code.
// But, of course, I don't want to start the whole project, so:
/*
// The real project starts here...
*/
}
or create a second method.
// But, of course, I don't want to start the whole project, so:
// realProject();
}
public static void realProject()
// The real project starts here...
}
Some people consider multiple return statements as bad programming style. While this is true for larger methods, I'm not sure if it is acceptable for short ones. But there is another question: Should else explicitly be written, if there is a return statement in the previous if?
Implicit else:
private String resolveViewName(Viewable viewable) {
if(viewable.isTemplateNameAbsolute())
return viewable.getTemplateName();
return uriInfo.getMatchedResources().get(0).getClass().toString();
}
Explicit else:
private String resolveViewName(Viewable viewable) {
if(viewable.isTemplateNameAbsolute())
return viewable.getTemplateName();
else
return uriInfo.getMatchedResources().get(0).getClass().toString();
}
Technically else is not necessary here, but it make the sense more obvious.
And perhaps the cleanest approach with a single return:
private String resolveViewName(Viewable viewable) {
String templateName;
if(viewable.isTemplateNameAbsolute())
templateName = viewable.getTemplateName();
else
templateName = uriInfo.getMatchedResources().get(0).getClass().toString();
return templateName;
}
Which one would you prefer? Other suggestions?
Other obvious suggestion: use the conditional operator.
private String resolveViewName(Viewable viewable) {
return viewable.isTemplateNameAbsolute()
? viewable.getTemplateName()
: uriInfo.getMatchedResources().get(0).getClass().toString();
}
For cases where this isn't viable, I'm almost certainly inconsistent. I wouldn't worry too much about it, to be honest - it's not the kind of thing where the readability is like to be significantly affected either way, and it's unlikely to introduce bugs.
(On the other hand, I would suggest using braces for all if blocks, even single statement ones.)
i prefer the cleanest approach with single return.To me code is readable, maintainable and not confusing.Tomorrow if you need to add some lines to the if or else block it is easy.
1.) code should never be clever.
The "single point of exit" dogma comes from the days of Structured Programming.
In its day, structured programming was a GOOD THING, especially as an alternative to the GOTO ridden spaghetti code that was prevalent in 1960's and 1970's vintage Fortran and Cobol code. But with the popularity of languages such as Pascal, C and so on with their richer range of control structures, Structured Programming has been assimilated into mainstream programming, and certain dogmatic aspects have fallen out of favor. In particular, most developers are happy to have multiple exits from a loop or method ... provided that it makes the code easier to understand.
My personal feeling is that in this particular case, the symmetry of the second alternative makes it easiest to understand, but the first alternative is almost as readable. The last alternative strikes me as unnecessarily verbose, and the least readable.
But #Jon Skeet pointed out that there is a far more significant stylistic issue with your code; i.e. the absence of { } blocks around the 'then' and 'else' statements. To me the code should really be written like this:
private String resolveViewName(Viewable viewable) {
if (viewable.isTemplateNameAbsolute()) {
return viewable.getTemplateName();
} else {
return uriInfo.getMatchedResources().get(0).getClass().toString();
}
}
This is not just an issue of code prettiness. There is actually a serious point to always using blocks. Consider this:
String result = "Hello"
if (i < 10)
result = "Goodbye";
if (j > 10)
result = "Hello again";
At first glance, it looks like result will be "Hello again" if i is less than 10 and j is greater than 10. In fact, that is a misreading - we've been fooled by incorrect indentation. But if the code had been written with { } 's around the then parts, it would be clear that the indentation was wrong; e.g.
String result = "Hello"
if (i < 10) {
result = "Goodbye";
}
if (j > 10) {
result = "Hello again";
}
As you see, the first } stands out like a sore thumb and tells us not to trust the indentation as a visual cue to what the code means.
I usually prefer the first option since it's the shortest.
And I think that any decent programmer should realize how it works without me having to write the else or using a single return at the end.
Plus there are cases in long methods where you might need to do something like
if(!isValid(input)) { return null; }// or 0, or false, or whatever
// a lot of code here working with input
I find it's even clearer done like this for these types of methods.
Depends on the intention. If the first return is a quick bail-out, then I'd go without the else; if OTOH it's more like a "return either this or that" scenario, then I'd use else. Also, I prefer an early return statement over endlessly nested if statements or variables that exist for the sole purpose of remembering a return value. If your logic were slightly complex, or even as it is now, I'd consider putting the two ways of generating the return value into dedicated functions, and use an if / else to call either.
I prefer multiple returns in an if-else structure when the size of both statements is about equal, the code looks more balanced that way. For short expressions I use the ternary operator. If the code for one test is much shorter or is an exceptional case, I might use a single if with the rest of the code remaining in the method body.
I try to avoid modifying variables as much as possible, because I think that makes the code much harder to follow than multiple exits from a method.
Keep the lingo consistent and readable for the lowest common denominated programmer who might have to revisit the code in the future.
Its only a few extra letters to type the else, and makes no difference to anything but legibility.
I prefer the first one.
Or... you can use if return else return for equally important bifurcations, and if return return for special cases.
When you have assertions (if p==null return null) then the first one is the most clear by far. If you have equally weighted options... I find fine to use the explicit else.
It's completely a matter of personal preference - I've literally gone through phases of doing all 4 of those option (including the one Jon Skeet posted) - none of them are wrong, and I've never experienced any drawbacks as a result of using either of them.
The stuff about only one return statement dates from the 1970s when Dijkstra and Wirth were sorting out structured programming. They applied it with great success to control structures, which have now settled down according to their prescription of one entry and one exit. Fortran used to have multiple entries to a subroutine (or possibly function, sorry, about 35 years since I wrote any), and this is a feature I've never missed, indeed I don't think I ever used it.
I've never actually encountered this 'rule' as applied to methods outside academia, and I really can't see the point. You basically have to obfuscate your code considerably to obey the rule, with extra variables and so on, and there's no way you can convince me that's a good idea. Curiously enough, if you write it the natural way as per your first option the compiler usually generates the code according to the rule anyway ... so you can argue that the rule is being obeyed: just not by you ;-)
Sure, people have a lot to say about programming style, but don't be so concerned about something relatively trivial to your program's purpose.
Personally, I like to go without the else. If anybody is going through your code, chances are high he won't be too confused without the else.
I prefer the second option because to me it is the quickest to read.
I would avoid the third option because it doesn't add clarity or efficiency.
The first option is fine too, but at least I would put a blank line between the first bit (the if and its indented return) and the second return statement.
In the end, it comes to down to personal preference (as so many things in programming style).
Considering multiple return statements "bad style" is a long, long discredited fallacy. They can make the code far clearner and more maintainable than explicit return value variables. Especially in larger methods.
In your example, I'd consider the second option the cleanest because the symmetrical structure of the code reflects its semantics, and it's shorter and avoids the unnecessary variable.