1

Why compiler gives me "return statement missing" erorr?

All possible conditional branches (if-else) contain a return statement.

But if I have the same if-else-if-else construct alone (not inside for() loop) - it compiles fine, without producing this "return statement missing" erorr?

public Resume get(String uuid) {

        // compiler shall know that array is not empty!
        final Resume[] storage = new Resume[100]; // same for static final

        // is executed at least once - see above!
        for(Resume resume : storage) {
            if (resume == null) {
                return null;                
            } else if (resume.uuid.equals(uuid)){
                return resume;
            }  else {
                return null;
            }            
        }
        // return statement is missing !!!      
    }

I could understand the compiler - it is afraid that the loop would never execute if the array named storage is empty. Why compiler ignores the size of the array? But it is just a half of problem with advanced for loop.

Let's take a regular for loop, totally independant of storage array size.

public Resume get(String uuid) {
        Resume resume = new Resume();

        // being a static final field produces same compile error...
        final int LIMIT = 100;

        // LIMIT is known to compiler, since it is final primitive.
        // for loop execution not dependent on storage array being empty
        for (int i = 0; i < LIMIT; i++) {       
            if (resume == null) {
                return null;                
            } else if (resume.uuid.equals(uuid)){
                return resume;
            }  else {
                return null;
            }            
        }
        // return null;   //statement is missing !!!; //       
    }

What explains this second for loop problem?

P.S. I think it is because things like "i < LIMIT" (even LIMIT being final) do not evaluate to true during compilation, true appears only at runtime, so at compile-time compiler is afraid just-in-case ;)

4
  • 7
    What if storage is empty? Compiler doesn't assume its size, it takes into consideration scenario where loop may not iterate even once. Commented May 28, 2018 at 12:49
  • 1
    Because there's a path through get that doesn't return anything: The path taken if storage is empty. You and I know that it isn't empty, but the compiler doesn't work down to that level of detail. Separately, it doesn't make any sense to use a loop if you're only ever going to have a single iteration (because you're returning immediately). Commented May 28, 2018 at 12:51
  • 1
    this loop is not executed "at least once" as stated in the comment, but only once if storage is not empty, as tthe method will return during the first iteration. Remove the last else block to go through the list Commented May 28, 2018 at 12:53
  • Re edit: Even if LIMIT is final so compiler can assume its value, i is not so compiler will not assume its value (even if we know that it will be 0 at start) probably because that value will be set at runtime (compiler is not that smart yet, although it would be nice if it was). So at compilation-time i < LIMIT is similar to ? < LIMIT so compiler can't evaluate that expression to be true which would guarantee that loop would iterate at least once. Problem disappears when instead of i < LIMIT you will compare two compilation-time constants or use true instead of condition. Commented May 28, 2018 at 13:18

5 Answers 5

3

Even though you assign a non empty array to the storage variable, the compiler doesn't take that into account when considering whether all execution paths have a return statement.

As far as the compiler is concerned, it's possible that the for loop will have 0 iterations, and therefore there must be a return statement after the loop.

In fact, even if you use only constants in the loop's condition, the compiler will still require a return statement after the loop. The following method won't pass compilation:

public static int test() 
{
    for (int i = 0; i < 5; i++) {
        return 3;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

If storage will be empty, no return will occure.

Comments

0

What if your storage is empty, you will never go into loop, thus you wouldn't reach any of your return statements.

At compile time you couldn't guarantee that your collections would never be empty, thus compiler need a return statement for this branch of execution.

Comments

0

all possible conditional branches are in for loop, what if your storage array is empty than return statement is not reachable that's why compiler giving you this error

Comments

0

Change your code like this because if storage is empty, it pass the for:

public Resume get(String uuid) {

        // compiler shall know that array is not empty!
        final Resume[] storage = new Resume[100]; // same for static final

        // is executed at least once - see above!
        for(Resume resume : storage) {
            if (resume == null) {
                return null;                
            } else if (resume.uuid.equals(uuid)){
                return resume;
            }  else {
                return null;
            }            
        }
        return null;      
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.