I recently rediscovered the use of breaking back to a label. Now I'm wondering if it is possible to break back to a label from another class.
Example of what i want:
Main.class
label:
for (Product p : ProductList) {
if (p.getSet() == true) {
classHandler();
}
}
Classhandler.class
someFunction() {
break label;
}
While I was typing this I actually tried making a local function in my Main class (so I could just call that function instead) but even there I got the undefined label: label error.
No, you can't. And you shouldn't.
If the condition for breaking is some problem, then throwing an exception would be the correct approach.
Otherwise you should do something like returning a flag that indicates if other products should still be handled and reacting on that in your loop.
As you noticed you can't even break through method-borders, and that's a good thing. break and continue are powerful tools, but can easily make your code confusing, if used in the wrong way. For example a break hidden inside a huge code block can be easy to miss, but if you use a continue at the very top of a method to skip an iteration based on some condition, then the intention is pretty clear.
The label that you break to must be in scope. From the java sun documentation:
A break statement with label Identifier attempts to transfer control
to the enclosing labeled statement (§14.7) that has the same
Identifier as its label; this statement, which is called the break
target, then immediately completes normally. In this case, the break
target need not be a while, do, for, or switch statement. A break
statement must refer to a label within the immediately enclosing
method or initializer block. There are no non-local jumps
No, you cannot. That does not even work between two methods of the same class. Labels are scoped (at the most) within a single method.
It doesn't make sense, since there is no guarantee that label exists, not even that someFunction() is called within a loop.
Related
while browsing some source code i noticed a weird operator being used on a while loop
topLoop: while(dist < 0){
random code...
}
what does the 'topLoop:' mean in this situation? and what does it do to the while exactly?
p.s. topLoop is just a int defined earlier on in the code.
The colon is not an operator. The topLoop: is called a label. You can use it, for example, to directly jump from a nested loop to outside the outer loop.
There's probably a break topLoop; statement somewhere inside the loop that you didn't show. This will make execution jump to the topLoop label.
Labels are used only seldomly in practice, and in my opinion using labels is bad practice - they are a kind of goto statement, and using them can quickly make your code a hard to understand, tangled mess.
p.s. topLoop is just a int defined earlier on in the code.
Maybe the code has a variable named topLoop, but this has nothing to do with the label that happens to have the same name.
I call a method with a variable x, I make some checks and if some conditions are true I have to execute part of the same method with a different variable value.
What is more effective?
to call the method again (recursion), or
to change the value of my variable and leave the program to execute the following lines of the method?
In both cases i can make it work but what is the more efficient way?
For the second case, I use an if statement on top. I read the value I want and then the following if statements are executed using this value.
public void mymethod(x){
if (con){
x = something;
}
if (con2){
//do something
} else if(con3) {
//do something
}
}
As Dave said, you probably should not be concerned at all about such micro-optimizations. The best thing to do is to write your code in such a way that it is easiest to read and understand. The best approach in my opinion would be to move the "do something" part into a separate function, and pass to it all the parameters that it needs in order to do its job.
If you really want to get down to efficiency talk, be advised that modern systems tend to rely heavily on caching, so many approaches to performance which used to work in the past do not actually constitute improvements anymore. On the contrary, they worsen things.
it is more efficient to modify the value of x and continue the method execution. The reason is simple. When you call a function, the caller state must be saved (into a stack) then local variables of the called method are read and so the called method is executed. So, being already in the called method myMethod it'd be "cheaper" to access the variable x to modify its value and then continue
I always thought that the labels must be used only with loops but it seems not. Giving such code:
public class LabelTest {
public static void main(String[] args) {
label1: System.out.println("");
label2: LabelTest t = new LabelTest();
}
}
When compiled line labeled "label1" compiles but the code at "label2" gives errors. Why's that? And why would I want to label statements which are not "loops"?
You get an error because a label cannot be applied to variable declarations, that's just how the language grammar is defined (a label can only precede a Statement, and a LocalVariableDeclarationStatement is not a Statement). The reason is probably that it could cause confusion concerning variable scope. This works:
label1: System.out.println("");
label2: { LabelTest t = new LabelTest(); }
To add to Michael Borgwardt's answer, you can do things like this for convenience (I just discovered this the other day while reading through the Java rt.jar source code):
BlockSegment:
if (conditionIsTrue) {
doSomeProcessing ();
if (resultOfProcessingIsFalse()) break BlockSegment;
otherwiseDoSomeMoreProcessing();
// These lines get skipped if the break statement
// above gets executed
}
// This is where you resume execution after the break
anotherStatement();
Now, this is logically equivalent to:
if (conditionIsTrue) {
doSomeProcessing ();
if (!resultOfProcessingIsFalse()) {
otherwiseDoSomeMoreProcessing();
// More code here that gets executed
}
}
anotherStatement();
But, you get to skip some of the extra braces (and indentations that come with braces). Perhaps it looks cleaner (it does in my opinion), and there are some places where this style of coding may be appropriate and less confusing.
So, you may use labels beyond just loops, and even beyond if statements. For example, this is valid Java syntax (and maybe you could conjure up a reason to do something like this):
statementOne();
statementTwo();
BlockLabel: {
statementThree();
boolean result = statementFour();
if (!result) break BlockLabel;
statementFive();
statementSix();
}
statementSeven();
If the break gets executed here, then execution skips to the end of the block denoted by the label, and statementFive() and statementSix() get skipped.
The usefulness of this style (without an if statement) becomes more evident when you have blocks within blocks where you must skip around. In general, you can accomplish everything with smart enough use of loops. However, there are a few cases where labels without loops make for easier reading of code. For example, if you need to sequentially check parameters, you may either do this or throw an exception. It ends up being a matter of cleanliness of code and personal style.
It does not compile. Good question!
I have just played a little bit with your code snippet. It seems that compiler expects method call or operator after label. It does not allow assignment at this point.
I think that the fact that label is not forbidden before operators other than for, while and do is probably a bug (?!) of java compiler of specification. Anyway it is not so critical. It does not bother me (personally).
Java syntax is based on C syntax.
In C you can put a label anywhere (not just on loops) and then use goto to jump the execution to that line. Now, goto wasn't implemented in Java, but labels were left so that they can be used in combination with break or continue.
It's not that important since this isn't a standard use of labels anyway. Using labels with continue or break is bad enough (most of the times). Using them freely is also useless.
I am little late to answer this. Anyway,
label2: LabelTest t = new LabelTest(); -> Doesn't work because it is a declarative statement, as most of the above comments state the same. To make it work just do the following:
label2: new LabelTest(); // works fine
Refer to Lable in JLS
If "flag" is true I have to perform step no. 1 otherwise skip it. Is there a way out to skip this unnecessary repetitive check within the loop. (As the value of flag is not changing while the execution of the loop)
private void method(boolean flag) {
while (man > woman) {
if (flag) {
// Step no. 1
System.out.println(flag);
}
}
}
I'm not sure it is productive to worry about optimizations at this level. Generally it is more important to get the program working and move on to the next problem.
Having said that, there is an optimization called loop unswitching that some compilers will do for you. They duplicate the loop, once with and once without the conditional, and move the conditional outward to select the loop. (In your example you could make the entire loop conditional but I presume that's just an artifact of simplification for Stack Overflow.)
But this is just one more reason not to worry too much about optimizations, at least, not until you have a profile and you know that this region of code is responsible for detectable amounts of runtime.
Still, it's best to write code as cleanly as you can and puzzling through issues like this will teach you good things...
In fact, loop-invariant conditionals bother me too. I don't believe there is a general answer. There are fancy answers involving higher order functions or lambdas, "leave-it-to-the-compiler" answers, refactor-the-whole-outer-routine answers ... I would generally approve of whatever makes the code appear smaller. You have to prioritize in order to discriminate...
It depends on the scope of do. If do is always true, you don't need to check for it and you can remove if (do). There is no reason to set a variable to true if it will always be true. What is the scope?
If the value of do changes at any time in the loop, you have to check for it every time unless you rewrite the code so that the do == true state is handled outside the current loop (perhaps in a smaller loop; it depends on what you're trying to do [no pun intended]).
while (man > woman) {
Beware of infinite loops here :-)
Given the following code sample:
public class WeirdStuff {
public static int doSomething() {
while(true);
}
public static void main(String[] args) {
doSomething();
}
}
This is a valid Java program, although the method doSomething() should return an int but never does. If you run it, it will end in an infinite loop. If you put the argument of the while loop in a separate variable (e.g. boolean bool = true) the compiler will tell you to return an int in this method.
So my question is: is this somewhere in the Java specification and are there situation where this behavior might be useful?
I'll just quote the Java Language Specification, as it's rather clear on this:
This section is devoted to a precise explanation of the word "reachable." The idea is that there must be some possible execution path from the beginning of the constructor, method, instance initializer or static initializer that contains the statement to the statement itself. The analysis takes into account the structure of statements. Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
...
A while statement can complete normally iff at least one of the following is true:
The while statement is reachable and the condition expression is not a constant expression with value true.
There is a reachable break statement that exits the while statement.
...
Every other statement S in a nonempty block that is not a switch block is reachable iff the statement preceding S can complete normally.
And then apply the above definitions to this:
If a method is declared to have a return type, then every return statement (§14.17) in its body must have an Expression. A compile-time error occurs if the body of the method can complete normally (§14.1).
In other words, a method with a return type must return only by using a return statement that provides a value return; it is not allowed to "drop off the end of its body."
Note that it is possible for a method to have a declared return type and yet contain no return statements. Here is one example:
class DizzyDean {
int pitch() { throw new RuntimeException("90 mph?!"); }
}
Java specification defines a concept called Unreachable statements. You are not allowed to have an unreachable statement in your code (it's a compile time error). A while(true); statement makes the following statements unreachable by definition. You are not even allowed to have a return statement after the while(true); statement in Java. Note that while Halting problem is undecidable in generic case, the definition of Unreachable Statement is more strict than just halting. It's deciding very specific cases where a program definitely does not halt. The compiler is theoretically not able to detect all infinite loops and unreachable statements but it has to detect specific cases defined in the spec.
If you are asking if infinite loops can be useful, the answer is yes. There are plenty of situations where you want something running forever, though the loop will usually be terminated at some point.
As to your question: "Can java recognized when a loop will be infinite?" The answer is that it is impossible for a computer to have an algorithm to determine if a program will run forever or not. Read about: Halting Problem
Reading a bit more, your question is also asking why the doSomething() function does not complain that it is not returning an int.
Interestingly the following source does NOT compile.
public class test {
public static int doSomething() {
//while(true);
boolean test=true;
while(test){
}
}
public static void main(String[] args) {
doSomething();
}
}
This indicates to me that, as the wiki page on the halting problem suggests, it is impossible for there to be an algorithm to determine if every problem will terminate, but this does not mean someone hasn't added the simple case:
while(true);
to the java spec. My example above is a little more complicated, so Java can't have it remembered as an infinite loop. Truely, this is a weird edge case, but it's there just to make things compile. Maybe someone will try other combinations.
EDIT: not an issue with unreachable code.
import java.util.*;
public class test {
public static int doSomething() {
//while(true);
while(true){
System.out.println("Hello");
}
}
public static void main(String[] args) {
doSomething();
}
}
The above works, so the while(true); isn't being ignored by the compiler as unreachable, otherwise it would throw a compile time error!
Yes, you can see these 'infinite' loops in some threads, for example server threads that listen on a certain port for incoming messages.
So my question is: is this somewhere in the Java specification
The program is legal Java according to the specification. The JLS (and Java compiler) recognize that the method cannot return, and therefore no return statement is required. Indeed, if you added a return statement after the loop, the Java compiler would give you a compilation error because the return statement would be unreachable code.
and are there situation where this behavior might be useful?
I don't think so, except possibly in obscure unit tests.
I occasionally write methods that will never return (normally), but putting the current thread into an uninterruptible infinite busy-loop rarely makes any sense.
After rereading the question....
Java understands while(true); can never actually complete, it does not trace the following code completely.
boolean moo = true;
while (moo);
Is this useful? Doubtful.
You might be implementing a general interface such that, even though the method may exit with a meaningful return value, your particular implementation is a useful infinite loop (for example, a network server) which never has a situation where it should exit, i.e. trigger whatever action returning a value means.
Also, regarding code like boolean x = true; while (x);, this will compile given a final modifier on x. I don't know offhand but I would imagine this is Java's choice of reasonable straightforward constant expression analysis (which needs to be defined straightforwardly since, due to this rejection of programs dependent on it, it is part of the language definition).
Some notes about unreachable statements:
In java2 specs the description of 'unreachable statement' could be found. Especially interesting the following sentence:
Except for the special treatment of while, do, and for statements whose condition expression has the constant value true, the values of expressions are not taken into account in the flow analysis.
So, it is not obviously possible to exit from while (true); infinite loop. However, there were two more options: change cached values or hack directly into class file or JVM operating memory space.