Uncommonly used Java syntax (JavaParser)? - java

I'm exploring a Java grammar parser and I came across this strange piece of code that I wouldn't normally use in ordinary code. Taken from
https://code.google.com/p/javaparser/source/browse/branches/mavenized/JavaParser/src/main/java/japa/parser/ASTParser.java#1998
It has many functions that contains code such as
final public NameExpr Name() throws ParseException {
NameExpr ret;
jj_consume_token(IDENTIFIER);
ret = new NameExpr(token.beginLine, token.beginColumn, token.endLine, token.endColumn, token.image);
label_23: while (true) {
if (jj_2_17(2)) {
;
} else {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
}
{
if (true) {
return ret;
}
}
throw new Error("Missing return statement in function");
}
At a glance it appears strange but no doubt it's valid as I can compile it. But can someone explain how it works? I have tried to input invalid Java syntax and it does it's job! I'm baffled. How does the few lines throw exception after the return?

This is indeed valid code, without seeing everything, I can see some odditities:
'Incorrect' variable and method naming, using PascalCase sometimes.
Instance variable token
Static variable IDENTIFIER
Then:
label_23: while (true) {
if (jj_2_17(2)) {
;
} else {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
}
This is an infinite loop that keeps running as long as jj_2_17(2) returns true, but appears to do nothing upon that result. It breaks out of label_23 when the expression was false. To confuse future readers even more, it then actually does things only if the expression is true (as it breaks on false), namely the last three lines.
For futher information, the label_23 is simply a label that may only be used on while and for loops. You can then break out of that loop when using break labelName;.
Example that breaks out of an outer loop from within an inner loop:
outerLoop: for (int i = 0; i < max; i++) {
innerLoop: for (int j = 0; j < max2 - i; j++) {
if (something) {
break outerLoop;
}
//...
}
}
You can actually also use continue in combination with labels.
Then we see a scoped block without guard that always returns ret:
{
if (true) {
return ret;
}
}
So it's all valid. I think we can also conclude with high chance that this code has been machine-generatd.

What maybe largely confused here is that if-else block inside the while.
if (jj_2_17(2)) {
;
} else {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
this is in fact nothing other than a negated if:
if(!jj_2_17(2)) {
break label_23;
}
jj_consume_token(DOT);
jj_consume_token(IDENTIFIER);
ret = new QualifiedNameExpr(ret.getBeginLine(), ret.getBeginColumn(), token.endLine, token.endColumn, ret, token.image);
So in fact this code just returns the last QualifiedNameExpr(/*...*/); that could be parsed.
Concerning the "unreachable throw" you mention in comments. Just imagine what happens when you create a method (in eclipse or netbeans) and don't add a return statement.
The generated code (assuming this is generated code here) then contains no return statement and suddenly you get to throw the Error. This leads to eclipse/netbeans/[insert IDE here] telling you "Missing return statement in function", which is exactly what this statement is there for...

Related

Having trouble understanding return type placement( Big Java Ex 6.8)

Currently on the chapter in my book where we talk about for loops and loops. I have sometimes come across an issue where the method needs me to return something. For example consider my code
below. Basically the exercise is to get all the factors in ascending order. Now heres the issue
As you can see I need a return statement outside of the for loop. Now I guess my book didn't exactly explain this properly, or I didn't understand the concept
of return properly in java, but does our return statement always have to be in the most outer indentation if you will?
The thing is, I don't really want to return anything outside of the for loop. I just want to return i upon that condition. Why doesn't java let me do this?
Whats a good counter-action?
Ever since I started learning loops and for loops, I have been having trouble understanding this. I guess I could just system.out.println(i) instead of returning it? But then what should I return? I could also make it a void type, and then make another method to print it, I guess?
class factors{
private int num;
public factors(int num)
{
this.num = num;
}
public int getFactors()
{
for(int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
return i;
}
}
// I NEED TO PUT A RETURN STATEMENT HERE
}
}
public class test{
public static void main(String [] args)
{
factors fact = new factors(20);
System.out.println(fact.getFactors());
}
}
IT WORKS NOW ( I dont particularly like my solution)
class factors{
private int num;
public factors(int num)
{
this.num = num;
}
public void getFactors()
{
for(int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
System.out.println(i);
}
}
}
}
public class test{
public static void main(String [] args)
{
factors fact = new factors(20);
fact.getFactors();
}
}
The thing is, I don't really want to return anything outside of the for loop. I just want to return i upon that condition. Why doesn't java let me do this?
Java lets you do that. There is nothing wrong with returning inside the loop upon reaching the condition.
Java allows you to have multiple return statements, so adding another return 0; after the loop is allowed.
Java returns once it hits the first return statement, and other return statements are not executed (the method isn't executed anymore) (except for some rare edge cases with try-catch and return, but thats another story entirely).
But why is it required?
Java requires that for all possible paths there exists a return with the proper type. Even if you yourself can proof mathematically that the path Java complains about is never taken, the compiler might not be able to prove that the path is not possible at runtime. So you simply need to add an return there with a dummy value.
In your concrete example, there is a condition in which the loop gets never executed. If num <= 0, then the loop condition is never satified and the entire loop body is skipped. Without the return,the method is invalid, because you can't return nothing from an method with return type int.
So, in your example, the compiler is actually smarter then you, and prevents you from making a mistake - because it found the path you thought wouldn't occur.
new factors(-1).getFactors(); // you don't check the passed value at all ;)
From your comments, it seems that you want to return all factors. In java, you return once, and only once, from a function. This means you have to aggregate the results and return a List or array of values:
public List<Integer> getFactors(int num) {
List<Integer> factors = new ArrayList<>();
for (int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
factors.add(i);
}
}
return factors;
}
public static void main(String[] args) {
System.out.println(Arrays.toString(new factors(20).getFactors());
// prints a comma-separated list of all factors
}
does our return statement always have to be in the most outer indentation if you will?
No.
However, all potential code paths must return something. Consider this structure:
for(int i = 1 ; i<num ; i++)
{
if (num % i == 0)
{
return i;
}
}
What happens if num is a value where the loop itself is never entered? Or what happens if the if condition is never satisfied? No return statement would ever be encountered, which is invalid.
The compiler has to guarantee that the method will return something, under any and all potential runtime conditions. So while it's perfectly valid to return from within the loop, you also must provide logic for what to return if that return statement is never reached.
Java doesn't let you do that because what happens if the if (num % i == 0) is never true?
The methods return type is int, so it has to return an int. And it's possible that the if statement could be false, not every condition is covered with a return statement.
So if you wanted to you could return something like -1, or another invalid value. Then you know that the function didn't find what it was looking for.

How to make sure a piece of code runs before a method exits

I have a method with if-else cases, and more than one return statement, depending on the exact flow.
I have one line of code that needs to happen just before the return statement (e.g. releaseResources).
I want to be sure that this line is executed no matter what.
Is there a nice way of doing that in java?
Something that will make sure a piece of code is executed before leaving a closure?
What you are looking for is a try-finally block. Here is an example:
public Something someMethod() {
try {
if(someStatement) {
return new Something();
} else {
return new SomethingElse();
}
} finally {
// this is always executed, even if there is an Exception
}
}
The question is if this is really what you want. It sounds like your code might actually be better (more readable) if it has two methods. Like this:
public Something createSomething() {
if(someStatement) {
return new Something();
} else {
return new SomethingElse();
}
}
public Something someMethod() {
Something something = createSomething();
// Do the thing that always needs to be done
return something;
}
This separates the things you are doing into two methods. Now if the problem is that the first method can throw an exception and you want to do something nonetheless, you can still use a finally. But it might be better to capture and handle the Exception.
Also: You've noted that you want to close a resource. In that case I would suggest you look into try-with-resources:
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
An example here:
private String someMethod() throws IOException {
// Java automatically closes the following Readers:
try (BufferedReader br =
new BufferedReader(new FileReader("/path"))) {
return br.readLine();
}
}
Depending of the programming language you're using, the try-catch-finally exist:
Example from other post about launch code after the if-else
Finally statement will launch when try-catch condition ends
SORRY FOR EDIT
You can use a try/finally block, if that's what you really want.
try {
if (...) return ...;
else if (...) return ...;
else return ...;
} finally {
doSomething();
}
The code in the finally block will always be executed when you leave the try block, in particular at any return statement.
The finally block will always be executed even if an Exception is thrown.
try {
...
if () {
return;
else {
return;
}
} finally {
// Release resources
}
One of the main programming good practices is that each method should have one and only one return statement. If you have many possible values, you tend to keep the value in an object and return it at the end.
E.g:
public int func(boolean condition) {
if(condition) {
return 1;
} else {
return 0;
}
}
should be made like this
public int func(boolean condition) {
int num;
if(condition) {
num = 1;
} else {
num = 0;
}
return num;
}
As you can probably see, it's quite simple to ensure you call your method before return this way, adding it right before the only return.

How is the return statement working in the following java method?

is it possible by any means in the following method that the print statement get executed after the if statement returns true in the for loop?
public boolean contains(Object o) {
if(o == null){
throw new IllegalArgumentException();
}
for(int i = 0; i < size(); i++){
if(o.equals(getNodeAt(i).data)){
System.out.println("contains passed here: "+o+" "+getNodeAt(i)+" "+i);
return true;
}
System.out.println(getNodeAt(1));
}
System.out.println("cointain failed here "+o);
return false;
}
Of course; call the method again. More effectively, efficiently, and specifically with an Object such that o.equals(getNodeAt(i).data is false. The truth is...
"[B]y any means" is a pretty loose constraint; you say...
is it possible by any means in the following method that the print statement get[s] executed after the if statement returns true in the for loop?
I'm saying that YES, that's possible by any means when the means are recalling the method. In fact, it's perpetually true as long as you're using whatever container.
Proof:
Assume that it is impossible by any means in the following method that the second return statement gets executed after the if statement returns true in the for loop.
static String proof(Object o) {
for(int i = 0; i < 1; ++i) {
if (o == null) {
return "I'm returning from the for loop!!!";
}
}
return "I'm now called after the for's return statement (by any means)!! - QED";
}
But given...
public static void main(String...args) {
System.out.println(proof(null));
System.out.println(proof(new String("Hello Proof!")));
}// end main method
the ouput is...
I'm returning from the for loop!!!
I'm now called after the for's return statement!! - QED
Therefore our assumption is wrong and it is possible by some means for the second return statement to get executed after the if statement returns true in the for loop.
;)
A "better" way to phrase that so it's clear what you're asking would be, perhaps, - "Is it possible for the code in a method body to continue to execute after a return statement?"
That answer is no and can be tested in any good IDE as follows.
static String proof(Object o) {
for(;;)
if(true)
return "Donkey Butts";
return "Poops";
}
This basically says forever it is true that I will return "Donkey Butts". In any IDE I'd waste my time using you will get an error for "unreachable statement". The IDE can determine this truth from your code which implicitly is telling you that any time the loop is active and the if is true the code below cannot execute.
No, it is definitely not possible.
No, but it is possible that System.out isn't flushed until after the return statement.
Yes, if you enclose in a try and finally.
public boolean contains(Object o) {
if(o == null){
throw new IllegalArgumentException();
}
for(int i = 0; i < size(); i++){
try {
if(o.equals(getNodeAt(i).data)){
System.out.println("contains passed here: "+o+" "+getNodeAt(i)+" "+i);
return true;
}
} finally {
System.out.println(getNodeAt(1));
}
}
System.out.println("cointain failed here "+o);
return false;
}
Nothing inside a method can be executed after the return statement.
But when you deal with output operations, things can happen quite differently from what you might expect. In fact, writes to an output file/device are often buffered, i.e. written to an internal array. When the array is full, it is sent to the file/device. This happens for efficiency reasons, because writing a few big chunks of data is faster than writing lots of small ones.
This means that these operations sometimes seem to happen long after the place where they appear in the code.

Why is eclipse asking me to add a return statement in this code even when I've added one?

Here is the code snippet:
private double input()throws IOException
{
StringTokenizer st=null;
BufferedReader b=new BufferedReader(new FileReader(csvfile));
String line=null;
int count=0;
while((line=b.readLine())!=null)
{
count+=1;
if(count==0)
{
return 0.0;
}
else
{
int sum=0;
String[] arr=new String[19];
st=new StringTokenizer(line,",");
int i=0;
while(st.hasMoreTokens())
{
arr[i]=st.nextToken();
i++;
}
for(int j=2;j<arr.length;j++)
{
if(j==13)
{
return Double.parseDouble(arr[j]);
}
}
System.out.println();
}
}
}
As you can see I've added a return statement for both cases of the if-else ladder. Eclipse is still asking me to add a return statement. Execution of the code raises an error for the same reason.(error : This method must return a result of type double)Why is this happening?
Background: The above method is to read a CSV file and return certain sections of the file as per the requirements of another method, which hasn't been shown here.
What happens if(j==13) returns false and never executes corresponding return? there is no return statement for this execution path right?
You need to have return statement for all executable paths.
There are several execution paths in your method that don't end in a return statement. All of them must do so. For example, the while loop might never be entered.
The easiest way to be absolutely sure is to add a return statement with a default value as the last statement.
There is no guarantee that else block return statement is going to execute,So you have to declare return statement outside.
In your case it is good practice to declare a variable outside and assigns it in if and else block and return it.
example:
double returnVariable = 0.0;
if(count==0)
{
returnVariable =0.0;
}
else
{
returnVariable = Double.parseDouble(arr[j]);
}
................
...........
return returnVariable ;
The problem is after this statement:
for (int j=2; j < arr.length; j++) {
if (j == 13) {
return Double.parseDouble(arr[j]);
}
}
If nothing is returned in that loop, Java is expecting you to return something afterwards. Java has no way to tell that the condition in the if is going to be true at some point, and in fact, it might never be true (what would happen if the array had less than 13 elements?).
The solution is to simply add an extra return at the end, with a returned value that makes it clear that the method exited under a non-expected circumstance - for example, if j was never equal to 13. Just add return -1.0; in the last line.
Your else part doesn't have a return statement directly. Instead it has it inside another if statement. Compiler can't determine if you will hot this check and returns.
In this section:
for(int j=2;j<arr.length;j++)
{
if(j==13)
{
return Double.parseDouble(arr[j]);
}
}
If you make it all the way through your loop, and don't find j = 13 (regardless if j is guaranteed to be there logically or not, programmatically that can't be determined by the compiler), then there is no applicable return statement.
You need to add a default case return statement AFTER your for loop.

while-else-loop

Of course this is an impossible statement in java (to-date), however ideally I would like to implement it as it is at the heart of many iterations. For example the first multiple times it is called I'm doing it 650,000+ times when it is creating the ArrayList.
Unfortunately the reality is that my actual code does not have the set inside the else loop; thus it will pass over both the add and then the set commands and wasting time.
After that I have it also in another loop where it is only performing the set as the data is already created and this is multi-nested with in many others so it is a lengthy process.
ArrayList<Integer> dataColLinker = new java.util.ArrayList<Integer>();
...
...
public void setLinkerAt( int value, int rowIndex) {
...
while(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
} else {
dataColLinker.set(rowIndex, value);
}
Any ideas or theories?
I'm unsure about speeds in java when it comes to if statements and ArrayList commands and so on
Am I missing something?
Doesn't this hypothetical code
while(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
} else {
dataColLinker.set(rowIndex, value);
}
mean the same thing as this?
while(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
}
dataColLinker.set(rowIndex, value);
or this?
if (rowIndex >= dataColLinker.size()) {
do {
dataColLinker.add(value);
} while(rowIndex >= dataColLinker.size());
} else {
dataColLinker.set(rowIndex, value);
}
(The latter makes more sense ... I guess). Either way, it is obvious that you can rewrite the loop so that the "else test" is not repeated inside the loop ... as I have just done.
FWIW, this is most likely a case of premature optimization. That is, you are probably wasting your time optimizing code that doesn't need to be optimized:
For all you know, the JIT compiler's optimizer may have already moved the code around so that the "else" part is no longer in the loop.
Even if it hasn't, the chances are that the particular thing you are trying to optimize is not a significant bottleneck ... even if it might be executed 600,000 times.
My advice is to forget this problem for now. Get the program working. When it is working, decide if it runs fast enough. If it doesn't then profile it, and use the profiler output to decide where it is worth spending your time optimizing.
I don't see why there is a encapsulation of a while...
Use
//Use the appropriate start and end...
for(int rowIndex = 0, e = 65536; i < e; ++i){
if(rowIndex >= dataColLinker.size()) {
dataColLinker.add(value);
} else {
dataColLinker.set(rowIndex, value);
}
}
boolean entered = false, last;
while (( entered |= last = ( condition ) )) {
// Do while
} if ( !entered ) {
// Else
}
You'r welcome.
Wrap the "set" statement to mean "set if not set" and put it naked above the while loop.
You are correct, the language does not provide what you're looking for in exactly that syntax, but that's because there are programming paradigms like the one I just suggested so you don't need the syntax you are proposing.
Java does not have this control structure.
It should be noted though, that other languages do.
Python for example, has the while-else construct.
In Java's case, you can mimic this behaviour as you have already shown:
if (rowIndex >= dataColLinker.size()) {
do {
dataColLinker.add(value);
} while(rowIndex >= dataColLinker.size());
} else {
dataColLinker.set(rowIndex, value);
}
This while else statement should only execute the else code when the condition is false, this means it will always execute it. But, there is a catch, when you use the break keyword within the while loop, the else statement should not execute.
The code that satisfies does condition is only:
boolean entered = false;
while (condition) {
entered = true; // Set it to true stright away
// While loop code
// If you want to break out of this loop
if (condition) {
entered = false;
break;
}
} if (!entered) {
// else code
}
Assuming you are coming from Python and accept this as the same thing:
def setLinkerAt(value, rowIndex):
isEnough = lambda i: return i < dataColLinker.count()
while (not isEnough(rowIndex)):
dataColLinker.append(value)
else:
dataColLinker[rowIndex] = value
The most similar I could come up with was:
public void setLinkerAt( int value, int rowIndex) {
isEnough = (i) -> { return i < dataColLine.size; }
if(isEnough()){
dataColLinker.set(rowIndex, value);
}
else while(!isEnough(rowInex)) {
dataColLinker.add(value);
}
Note the need for the logic, and the reverse logic. I'm not sure this is a great solution (duplication of the logic), but the braceless else is the closest syntax I could think of, while maintaining the same act of not executing the logic more than required.

Categories