Java loops compile errors

Can someone explain this to me? First of all, I know why this code

String getName(){
    for(;;){}
}

will violate a return type method: it's infinite, but why does this code need a final return value ?

String getName(){
    for(;i < limit; i++){// i is already defined
        if(someArrayList.get(i).isDead)
            continue;
        return someArrayList.get(i).name;
    }
    //needs a final return
}

The return value exists inside the loop and returns the value for the getName() method, so what is the reason? another post suggested that what if the loop is negative for my condition, so I rewrote it this way:

String getName(){
    for(; i < 10; i++){// i is already defined
        if((i+1) == limit){
            if(!someArrayList.get(i).isDead)
                return "";
        }else{
            if(someArrayList.get(i).isDead)
                continue;
            return someArrayList.get(i).name;
        }
    }
    // needs a final return
}

The same compile time error, even if I re-define i in the for loop condition, to 0 , so my i becomes zero and if the inner condition checks out negative I handle it myself. All in all, if I nest it in an infinite loop, it's ok.

String getName(){
    for(;;){
        for(; i < limit; i++){// i is already defined
            if(someArrayList.get(i).isDead)
                continue;
            return someArrayList.get(i).name;
        }
    }
}

Is it because it has a range? Because I feel it covers all scenarios, I just want to know why, before I add the last return and life's good

And lastly this works alright:

String getName(){
    for(;;){
        for(; i < limit; i++){// i is already defined
            if(someArrayList.get(i).isDead)
                continue;
            return someArrayList.get(i).name;
        }
        return "";
    }
}

Mr. skeet says this type of code is ok in java


You need a final return statement because your list may consist only of 'dead' entries, in which case your program will reach the 'limit' and exit the for loop.

I see the comments here, so a clarification is needed. The compiler simply cannot analyze all potential outcomes and decide with 100% certainty whether the loop will reach its natural end or not. It's theoretically impossible (you can read about The Halting Problem for more information).

While the compiler can figure it out sometimes, it usually only attempts to do that in relatively simple cases. The reason behind it is simple - if your code is complex enough so that it's unclear whether the loop ends or not - it'll confuse a human reader who won't understand why there's no return statement after the loop. Such code is bad code.


Because you can break from a loop. Generally you have to return something, that's what is expected to happen. Compiler is not a magician and cannot state if your loop condition is infinite or not (at least in most cases), in general it is run-time dependant.


NP Hard

Short version, what you are asking the computer to do is not just complicated or difficult but so hard there is a special term for it NP Hard, and has fairly good coverage here on Stack Overflow, see 'NP Hard vs NP Complete', or this question about proving the halting problem is NP Hard, or this question on Mathematics Stack Overflow , and last but not least see Wikipedia for the general definition of NP Hard. the compiler doesn't trust a conditional block and wants there to be a path to a return statement that doesn't depend on that conditional block.

The Curse of Turing

Long version, when the compiler evaluates the paths through the code, it creates a structure called a lattice to track all the different paths through the method. In the case where a method requires a return value the compiler uses the lattice by starting at the method exit point and examines all backwards paths looking for a return value. Yes your loop has a return statement but the compiler can't know in advance that your conditional block will always exit so it disregards that block when looking for the return value.

See the Halting Problem which actually address some of your examples but make sure you check out this answer which is my favorite simply for its charm. Your claim that the compiler should be able to tell that the loop will exit has merit if the compiler were to be coded to look for those specific code idioms; but that's the problem, there are too many special cases to code for making for a bloated compiler if that were attempted. So it generalizes the case and ignores conditional blocks when looking for a path to a return value.

Solution

What Jon Skeet said was it was ok to have more than one exit point in a method, he did not say it was ok to only have one exit point inside the conditional block.

There is a reason you see the following version of your code, it provides a default path for the return value, this is just one way to provide it.

String getName(){

    // default return value
    String retVal = "";

    for(;i < limit; i++){// i is already defined
        if(someArrayList.get(i).isDead)
            continue;
        return someArrayList.get(i).name;
    }

    //needs a final return
    return retVal;
}

When you say about the following code,

will violate a return type method: it's infinite, but why does this code need a final return value?

String getName(){
    for(;;){}
}

I would point out that the code requires one by defining a return value in the method declaration, so the following will not cause a compile error

void getName(){
    for(;;){}
}

and the question comes back to you as why you insist on declaring that a method must return something while also insisting on only using structures bounded by conditional blocks so the compiler can't detect that they will always execute.

Question

My question to you is why you don't just use a default return value, is there some reason you seem to be avoiding this approach? Not that it matters to me but it helps to know whether you have a pragmatic challenge like a coding standard or if it's more of a philosophic objection.

链接地址: http://www.djcxy.com/p/39986.html

上一篇: 混合整数编程可以解决多少个决策变量?

下一篇: Java循环编译错误