J2SE 1.5 provides another form of for loop. With this form of for loop, objects of types such as arrays and Collections can be traversed in a simpler way. This article introduces specific ways to use this loop, explains how to define your own classes that can be traversed in this way, and explains some common problems with this mechanism.
In a Java program, when you want to "process" - or "traverse" - the elements in an array or Collection one by one, you will usually use a for loop to achieve this (of course, use other Various types of loops are not impossible, but I don’t know whether it is because the length of the word for is relatively short, or because the meaning of the word for is more suitable for this kind of operation. In this case, the for loop is much more commonly used than other loops).
For traversing arrays, this loop is generally written like this:
List 1: Traditional way of traversing arrays
/* 建立一个数组 */ int[] integers = {1, 2, 3, 4}; /* 开始遍历 */ for (int j = 0; j < integers.length; j++) { int i = integers[j]; System.out.println(i); }
For traversing Collection objects, this loop is usually It takes the form:
Listing 2: The traditional way of traversing Collection objects
/* 建立一个Collection */ String[] strings = {"A", "B", "C", "D"}; Collection stringList = java.util.Arrays.asList(strings); /* 开始遍历 */ for (Iterator itr = stringList.iterator(); itr.hasNext();) { Object str = itr.next(); System.out.println(str); }
In the latest version of the Java language-J2SE 1.5, another form of for loop is introduced . With this form of for loop, you can now perform traversal work in a simpler way.
1. The second type of for loop
Strictly speaking, the second type of for loop in Java is basically in this format:
for (loop variable type loop variable Name: object to be traversed) Loop body
With this syntax, the operation of traversing an array can be written like this:
Listing 3: A simple way to traverse an array
/* 建立一个数组 */ int[] integers = {1, 2, 3, 4}; /* 开始遍历 */ for (int i : integers) { System.out.println(i); /* 依次输出“1”、“2”、“3”、“4” */ }
The for loop used here will be viewed as this form during compilation:
Listing 4: Equivalent code for a simple way of traversing an array
/* 建立一个数组 */ int[] integers = {1, 2, 3, 4}; /* 开始遍历 */ for (int 变量名甲 = 0; 变量名甲 < integers.length; 变量名甲++) { System.out.println(integers[变量名甲]); /* 依次输出“1”、“2”、“3”、“4” */ }
Here" Variable name "A" is a name automatically generated by the compiler that will not cause confusion.
The operation of traversing a Collection can be written like this:
Listing 5: A simple way to traverse a Collection
/* 建立一个Collection */ String[] strings = {"A", "B", "C", "D"}; Collection list = java.util.Arrays.asList(strings); /* 开始遍历 */ for (Object str : list) { System.out.println(str); /* 依次输出“A”、“B”、“C”、“D” */ }
The for loop used here will be in During compilation, it is viewed in the form:
Listing 6: Equivalent code for a simple way to traverse Collection
/* 建立一个Collection */ String[] strings = {"A", "B", "C", "D"}; Collection stringList = java.util.Arrays.asList(strings); /* 开始遍历 */ for (Iterator 变量名乙 = list.iterator(); 变量名乙.hasNext();) { Object str = 变量名乙.next(); System.out.println(str); /* 依次输出“A”、“B”、“C”、“D” */ }
The "variable name B" here is also automatically generated by the compiler A name that won't cause confusion.
Because during compilation, the J2SE 1.5 compiler will regard this form of for loop as the corresponding traditional form, so there is no need to worry about performance problems.
The reason why "foreach" and "in" are not used
Java uses "for" (rather than the more clear "foreach") to guide this kind of loop, which is generally called "for-each" ” loop, and use “:” (rather than the more explicit “in”) to separate the loop variable name and the object to be iterated over. The main reason for doing this is to avoid compatibility problems caused by the introduction of new keywords - in the Java language, keywords are not allowed to be used as variable names, although the name "foreach" is used Not very many, but "in" is a name often used to represent input streams (for example, in the java.lang.System class, there is a static attribute named "in", which means "standard input stream").
It is indeed possible to cleverly design the syntax so that keywords have special meanings only in specific contexts, allowing them to be used as ordinary identifiers. However, this strategy, which complicates grammar, has not been widely adopted.
The long history of “for-each loop”
The “for-each loop” is not a recent control structure. This control structure was already included in the Bourne shell (the first mature UNIX command interpreter) officially released in 1979 (the loop is guided by "for" and "in", and the loop body is guided by "do" and "done"). ” to identify).
2. Prevent loop variables from being modified in the loop body
By default, the compiler allows reassignment of loop variables in the loop body of the second for loop. However, because this approach has no impact on the situation outside the loop body and can easily cause difficulties in understanding the code, it is generally not recommended.
Java provides a mechanism to block such operations during compilation. The specific method is to add a "final" modifier in front of the loop variable type. In this way, assigning a value to the loop variable in the loop body will cause a compilation error. With the help of this mechanism, the intentional or unintentional operation of "modifying loop variables in the loop body" can be effectively prevented.
Listing 7: Disabling reassignment
ed48fdd9532ccb933604f76cc03c41e8清单10:使用和要被遍历的Collection中的元素相同类型的循环变量
Collection< String> strings = new ArrayList< String>();
strings.add("A");
strings.add("B");
strings.add("C");
strings.add("D");
for (String str : integers) {
System.out.println(str); /* 依次输出“A”、“B”、“C”、“D” */
}
循环变量的类型可以是要被遍历的对象中的元素的上级类型。例如,用int型的循环变量来遍历一个byte[]型的数组,用Object型的循环变量来遍历一个Collection< String>(全部元素都是String的Collection)等。
清单11:使用要被遍历的对象中的元素的上级类型的循环变量
String[] strings = {"A", "B", "C", "D"};
Collection< String> list = java.util.Arrays.asList(strings);
for (Object str : list) {
System.out.println(str);/* 依次输出“A”、“B”、“C”、“D” */
}
循环变量的类型可以和要被遍历的对象中的元素的类型之间存在能自动转换的关系。J2SE 1.5中包含了“Autoboxing/Auto-Unboxing”的机制,允许编译器在必要的时候,自动在基本类型和它们的包裹类(Wrapper Classes)之间进行转换。因此,用Integer型的循环变量来遍历一个int[]型的数组,或者用byte型的循环变量来遍历一个Collection< Byte>,也是可行的。
清单12:使用能和要被遍历的对象中的元素的类型自动转换的类型的循环变量
int[] integers = {1, 2, 3, 4};
for (Integer i : integers) {
System.out.println(i); /* 依次输出“1”、“2”、“3”、“4” */
}
注意,这里说的“元素的类型”,是由要被遍历的对象的决定的――如果它是一个Object[]型的数组,那么元素的类型就是Object,即使里面装的都是String对象也是如此。
可以限定元素类型的Collection
截至到J2SE 1.4为止,始终无法在Java程序里限定Collection中所能保存的对象的类型――它们全部被看成是最一般的Object对象。一直到J2SE 1.5中,引入了“泛型(Generics)”机制之后,这个问题才得到了解决。现在可以用Collection< T>来表示全部元素类型都是T的Collection。
更多Java for循环的几种用法分析相关文章请关注PHP中文网!