problem. What is the result of countOnes (int [])` `` when calling
main (...)` `` in the following Java code? So feel free to)?
SwitchSample.java
public class SwitchSample {
public static int countOnes(int[] numbers) {
int counter = 0;
for(int number : numbers) {
switch(number) {
case 0:
System.out.println("ZERO");
break;
case 1:
counter++;
default:
}
}
System.out.println("ONEs: " + counter);
return counter;
}
public static void main(String[] args) {
System.out.println("count: " + countOnes(new int[] { 1, 2, 3, 2, 1, 0, 3, 2, 1, 0, 4}));
}
}
If you think that the answer is 2, it's a shame because it hits `0``` while counting the number of
1``` in the array and breaks out of the
break;
`` loop. However, I fell into a trap.
Break after 2 lines of;Is**Escape from the switch statement**It doesn't escape from the for loop.
Therefore, the appearance of ``` 0``` in an array does not affect loop processing, so` `` `countOnes (int [])` `` is the number of all ``` 1``` in the array. The answer is 3 because it counts.
If you omit the ``` break;` `` after the ``` case 0:` `, the switch statement will" fall through "and be executed after the` `case 1:` ``, 1 Not only does it count the number of zeros.
#### **`After break to prevent "fallthrough";There can be criticism that should be written, but it doesn't matter if this is not the case.`**
```case 1
Looking at this example, don't you think, "Why is the statement that escapes from the loop and the statement that escapes from the switch statement the same?" I think.
Anyway, the question is, "In this case, how should I write the code to get out of the loop?"
If you modify the code as follows, the switch statement will break out of the loop with ``` case 0:` ``, and the answer to the first question will change to 2.
#### **`SwitchSample.java`**
```java
public class SwitchSample {
public static int countOnesBeforeZero(int[] numbers) {
int counter = 0;
loop: for(int number : numbers) {
switch(number) {
case 0:
System.out.println("ZERO");
break loop;
case 1:
counter++;
default:
}
}
System.out.println("ONEs: " + counter);
return counter;
}
}
The only difference is that the block of the for statement is labeled (loop) and specified in the break statement. It's easy, but block labels are rarely needed, so I'm sure there are quite a few Java programmers who say "I haven't written" or "I don't know the grammar." I also had a vague memory of grammar, and every time I wrote it, I searched online.
In the first place, the specification of the switch statement derived from C language that if a break statement is not written in the switch statement, it is executed by "falling through" to the statement after the next case label is too "statement of a single case label". It is easy to cause the illusion of a programmer that "only is executed", and created a large number of bugs due to forgetting to write a break statement. For this reason, "fallthrough" itself is regarded as a programming anti-pattern in modern times, and most programming languages that have become widespread in recent years no longer adopt switch statements that cause "fallthrough" in their language specifications. It's almost the last generation of programming languages that JavaScript and PHP fall through, and Java is the next oldest.
I wrote a little above, "Why is the statement that escapes from the loop and the statement that escapes from the switch statement the same?", But this is a statement that performs flow control that is similar to a loop such as while in C language. It seems that the reason is that Java has inherited the idea that it is natural to devote a break to escape. However, on the other hand, while the goto statement was used to get out of multiple loops at once in C language, why not add a goto statement to Java designed in the era when the concept of "structured programming" became widespread? Instead, I created the concept of a "labeled block" and made it possible (probably) to escape from the block by specifying the label with break. This has changed the functionality of break statements in Java, so I think I shouldn't have used the same reserved words as loop escapes to escape from switch statements.
Time has passed and Kotlin has been developed as a language for the Java Virtual Machine (JVM). The fallthrough switch statement that was not adopted even in Scala, the language for the previous generation JVM, is not adopted in Kotlin, and it can be used as an improved switch as an "expression" like Ruby's case-when The when expression was introduced. The when expression does not execute multiple blocks, and its behavior is if (...) {...} else if (...) else if (...) {...} else {.. It is almost the same as writing.} (In Kotlin, if statements can also be used as expressions).
Since the when expression no longer falls through, there is no longer a break in the when expression specification, and there is no need to worry about confusion with the break statement that breaks out of the loop. Therefore, the code "count the number of 1s, but exit the loop and end the process when it hits zero" can be written as:
SwitchSample.kt
object SwitchSample {
fun countOnesBeforeZero(numbers: IntArray): Int {
var counter = 0
for(number in numbers) {
when(number) {
0 -> {
println("ZERO")
break
}
1 -> {
counter++
}
else -> {}
}
}
println("ONEs: $counter")
return counter
}
@JvmStatic
fun main(args: Array<String>) {
println("count: " + countOnes(intArrayOf(1, 2, 3, 2, 1, 0, 3, 2, 1, 0, 4)))
}
}
You can build successfully with Kotlin 1.4, which just released a stable version the other day.
However, in Kotlin 1.3 and below
'break' and 'continue' are not allowed in 'when' statements. Consider using labels to continue/break from the outer loop
Error message is displayed and the build fails. "You can't use break and continue in a when statement. Consider using labels for continue / break in loops." ???
Don't panic. If your development environment cannot be updated to Kotlin 1.4 for some reason, please write as follows.
SwitchSample.kt
object SwitchSample {
fun countOnesBeforeZero(numbers: IntArray): Int {
var counter = 0
loop@ for(number in numbers) {
when(number) {
0 -> {
println("ZERO")
break@loop
}
1 -> {
counter++
}
else -> {}
}
}
println("ONEs: $counter")
return counter
}
}
As with the Java solution, label the block you want to escape and specify it in the break statement, and it will build normally.
The practical information in this article is
--Label is required if you want to use loop control break in Java switch statement --If you want to use loop control break / continue in Kotlin when expression, label is required only in Kotlin 1.3 or lower.
It's just (bitter smile).
Here explains why break / continue cannot be used without a label under Kotlin 1.3. -when-expressions-included-in-loops) (although I didn't think it was enough explanation).
If you write the same logic with if ~ else if ~ else without using when, this restriction does not exist, and break / continue can be used without a label even in Kotlin 1.3 or lower. As a test, using the "Convert if expression to when expression" function of Android Studio, write the logic using the unlabeled break statement in the if expression, and then convert the if expression to when expression. It was. Then, the loop block was automatically labeled, and a break statement with that label appeared.
The label was also given when I tried this conversion with the Kotlin 1.4 Android plugin, which should not require the label. Even if the language specifications change in Kotlin 1.4, the conversion process does not seem to change for the time being.
Recently, the number of Java code writing has decreased dramatically, and it is close to the situation where Kotlin should be used, so if you forget to label break in when statements under Kotlin 1.3, an error will occur. It looks like it should come out and correct it. However, if you omit the label required for break in the Java switch statement, an error will not occur and the meaning will change significantly, so be careful of programmers writing Java code.
I thought that the problem of "when break is used in a switch statement in a loop, which statement is the break" is a problem that is likely to occur in various programming languages, which is why I wrote this article. Therefore, I wrote some topics about programming languages other than Java and Kotlin, but I am not a programming language enthusiast, so I would like to leave only Java and Kotlin as the main person in charge and leave other languages to other authors for the time being. think.
However, when I searched the net, I couldn't find any content that I was worried about break in the switch statement in the loop. In that sense, this article may be highly original (laughs), but when most programmers see a break in a switch statement, even if it's inside a loop, "this break breaks out of the loop." It's rarely misread as "maybe a break to do", and it may not be a problem. When I came to that point, I realized that I had little memory of having trouble with this problem. So you can hardly expect more people to fall into the trap of the problem at the beginning (bitter smile).
What's New in Kotlin 1.4.0 - Using break and continue inside when expressions included in loops [switch statement-Wikipedia](https://ja.wikipedia.org/wiki/Switch statement)
Recommended Posts