Gradually excavate ENHANCED for loop easier traverse
Sun Haitao (Sun.haitao@126.com)
July 2004
J2SE 1.5 provides another form of FOR cycle. With this form of FOR cycle, you can use more simple to traverse an array and a type of collection. This article describes the specific ways of using this loop that explains how to define the classes that can be traversed and explain and explain some of the common problems in this mechanism.
In the Java program, "Top-by-one" - or say, "Traverse" - When the elements in a group or collection, a FOR loop is usually implemented (of course, using other types of cycles is not Yes, just don't know because the length of the word is relatively short, or because the meaning of the word is compared to this operation, it is often used in this time than other cycles.)
For traversal arrays, this cycle is generally taken:
Listing 1: Traditional ways to traverse arrays
/ * Establish an array * /
Int [] integers = {1, 2, 3, 4};
/ * Start traversing * /
For (int J = 0; j INT i = integers [j]; System.out.println (i); } For traversing Collection objects, this cycle is usually used in this form: Listing 2: Traditional ways to traverse Collection objects / * Create a collection * / String [] strings = {"a", "b", "c", "d"}; Collection stringlist = java.util.Arays.ASLIST (STRINGS); / * Start traversing * / 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 cycle, you can now use a simpler way to traverse. 2 second for cycle It is not strict, Java's second For loop is basically such format: FOR (cyclic variable type loop variable name : Objects to be traversed) cyclic body With this grammar, you can take such a way of writing in an array: Listing 3: Simple way to traverse arrays / * Establish an array * / Int [] integers = {1, 2, 3, 4}; / * Start traversing * / for (INT I: integers) { System.out.Println (i); / * Output "1", "2", "3", "4" * / } The for cycle used here will be seen in the compilation period: Listing 4: Equivalent code for traversing an array / * Establish an array * / Int [] integers = {1, 2, 3, 4}; / * Start traversing * / for (INT variable name = 0; variable name System.out.println (variable name); / * Output "1", "2", "3", "4" * / } The "variable name" here is a name that is automatically generated by the compiler without confusion. And the operation of traversing a Collection can also use such a way of writing: Listing 5: Simple way traversing Collection / * Create a collection * / String [] strings = {"a", "b", "c", "d"}; Collection list = java.util.Arrays.ASLIST (STRINGS); / * Start traversing * / for (Object str: List) { System.out.Println (STR); / * Output "A", "B", "C", "D" * / } The for cycle used here is that it is seen in the compilation period: Listing 6: Equivalent code for traversing Collection / * Create a collection * / String [] strings = {"a", "b", "c", "d"}; Collection stringlist = java.util.Arays.ASLIST (STRINGS); / * Start traversing * / for (Iterator Variable Name B = List.iterator (); Variable Name B.hasnext ();) { System.out.println (Variable Name B.Next ()); / * Output "A", "B", "C", "D" * / } "Variable Name B" here is also a name that is automatically generated by the compiler will not cause confusion. Because during compilation, J2SE 1.5 compiler will treat this form of Forcy, regard as a corresponding traditional form, so do not have to worry about performance problems. Reasons without "foreach" and "in" Java uses "for" (not meaningful "Foreach") to boot this generally called "For-Each loop", and use ":" (not meaningful "in") to split The loop variable name and the object to be traversed. The main reason for this is to avoid the problem of compatibility because of the introduction of new keywords - in the Java language, the keyword is not allowed as a variable name, although the name of "Foreach" is used. It is not very much, but "in" is a name that is often used to represent the input stream (such as a java.lang.system class, there is a Static property called "IN", indicating "standard input stream"). It is indeed a smart design grammar, allowing keywords to have special meaning in a particular context to allow them as a normal identifier. However, this kind of strategy that makes the grammar is not widely adopted. 2. Prevent modification of cyclic variables in the cycle By default, the compiler is allowed to re-value the loop variable in the cyclic body that is allowed in the second FOR cycle. However, because this practice has no effect on the situation outside the circulation, it is easy to understand the difficulty of understanding the code, so it is generally not recommended. Java provides a mechanism that can block such operations during compilation. The specific method is to add a "final" modifier in front of the cyclic variable type. In this way, it will cause a compilation error in the cyclic body. With this mechanism, you can effectively eliminate intentional or unintentional operation of "modifying the loop variable in the cycle body". Listing 7: Prohibition of reassignment Int [] integers = {1, 2, 3, 4}; FOR Final INT I: Integers) { i = I / 2; / * Compile time error * / } Note that this is only prohibiting reassigning the loop variable. Assign a value to the attribute of the loop variable, or the method of calling the content change of the loop variable is not prohibited. Listing 8: Allow modification status Random [] randoms = new random [] {new random (1), new random (2), new random (3)} FOR (Final Random R: Randoms) { r. SetSeed (4); / * Set all Random objects to use the same seed * / System.out.println (r.nextlong ()); / * The seed is the same, the first result is also the same * / } 3. Type compatibility In order to ensure that the cyclic variables can be assigned to each cycle, J2SE 1.5 has a certain limit on the type of loop variable. Under these restrictions, the type of cyclic variable can have some choices: The type of cyclic variable can be the same as the type of elements in the object to be traversed. For example, use int [] type arrays to traverse a Collection et al. With an Object type loop variable. Listing 9: Cyclic variables of the same type of elements in the object to be traversed Int [] integers = {1, 2, 3, 4}; FOR INT I: integers) { System.out.Println (i); / * Output "1", "2", "3", "4" * / } The type of cyclic variable can be the superior type of elements in the object to be traversed. For example, use int type loop variables to traverse a BYTE [] type array, use Object type loop variables to traverse a Collection String [] strings = {"a", "b", "c", "d"}; Collection < String> list = java.util.arrays.aslist (strings); FOR Object str: List) { System.out.Println (STR); / * Output "A", "B", "C", "D" * / } The type of loop variable can be automatically converted between the type of elements in the object to be traversed. The J2SE 1.5 contains "autoboxing / auto-unboxing" mechanisms, allowing compilers to automatically convert between the basic types and their wrappper classes when necessary. Therefore, use an INTEGER type loop variable to traverse an int [] type array, or use the Byte type loop variable to traverse a collection Int [] integers = {1, 2, 3, 4}; FOR Integer i: integers) { System.out.Println (i); / * Output "1", "2", "3", "4" * / } Note that "the type of element" here is determined by the object to be traversed - if it is an Object [] type array, then the type of element is Object, even if it is String object, it is also a String object. in this way. Can qualify for the type of Collection As of J2SE 1.4, it is never possible to qualify the type of object that can be saved in the Java program - they are all seen as the most general Object object. This issue has been resolved until J2SE 1.5 is introduced. This issue has been resolved after the "generics" mechanism. You can now use Collection There are two types of objects that can be traversed - arrays and implements instances of classes of the Java.lang.Iiterable interface. Attempting to put the result is that other types of expressions are placed in this position, only a prompt information is "Foreach Not Applicable To Expression Type" when compiling. The method defined in the java.lang.iterable interface is only one: Iterator () Returns an object that implements the Java.util.Iiterator interface In the Java.util.iterator interface, the three methods are defined: Hasnext () Return to whether there is an object that is not visited Next () Return to the next object that has not been accessed REMOVE () Remove the object returned by next () from the object being traversed. This is an optional operation. If this feature is not intended, throw a unsupportedOperationException when it is implemented. Because this method does not have the opportunity to be called throughout the cycle, this function is provided, there is no impact here. With these two interfaces, you can implement the class that can be traversed. Listing 12: A class that can take out 10 Object elements Import java.util. *; Class TenObjects IMPLEMENTS ITERABLE { Public iterator itrator () { Return new item () { PRIVATE INT count = 0; Public Boolean Hasnext () { Return (Count <10); } Public Object next () { Return New Integer (Count ); } Public void remove () { Throw new unsupportedOperationException (); } } } Public static void main (string [] args) { TenObjects Objects = new TenObjects (); For (Object i: Objects) { System.out.Println (i); / * Ten integers from "0" to "9" * / } } } Qualification of Collection In the J2SE 1.5 API, all the types of objects that can be traversed are java.util.collection subtypes, which look like Java.util.Collection to get the special treatment of the compiler. However, in the actual cause of this phenomenon is in J2SE 1.5, java.util.collection is defined as a sub-interface for java.lang.Iiterable. The compiler did not give Collection what special care. In theory, it is possible to make a container class that refuses to implement the Collection interface, and can be traversed in the same way as Collection. However, such a container class may not be widely circulated because there is a problem with compatibility. Several method of naming In the java.lang.ITerable interface, use iTerator () instead of getiterator (); and HasNext () and next () instead of HasNextElement () and getNextElement () instead of getiterator (); The reason for this phenomenon is the designers of Java Collections Framework, which is often called frequent calls (every time they are squeezed), so it is more appropriate to use a short name. 5. Add more precise type control If you want the cycle variable to use the more accurate type than Object, you need to use the Java.Lang.Istrable interface and Java.util.ITerator interface, with J2SE 1.5 Wild mechanisms to make some types of assignments. If you want to make the type of loop variables, the content assigned is: All in all Java.lang.Iitrable is written as "iTerable Note that T herein cannot be a basic type. If you plan to use a basic type as a loop variable, then use their wraps to replace the That here, then use the auto-unboxing mechanism to approximate the purpose. Listing 13: Use int type loop variables to traverse a class that removes 10 Integer elements Import java.util. *; Public Class Tenintegers Implements ITerable Public Iterator Return New Iterator PRIVATE INT count = 0; Public Boolean Hasnext () { Return (Count <10); } public INTEGER NEXT () { Return INTEGER.VALUEOF (Count ); } Public void remove () { Throw new unsupportedOperationException (); } } } Public static void main (string [] args) { Tenintegers integers = new tenintegers (); FOR INT I: integers) { System.out.Println (i); / * Ten integers from "0" to "9" * / } } } Alternatively, a class can only achieve a java.lang.ItemAble interface, even in the rear angle brackets use different types. Similar to "Class A Implements Iteerable With a second For loop introduced in J2SE 1.5, you can use a simpler place to complete traversal. The type of object that can be traversed by this method can be an array, collect, or any other class that implements a java.lang.iterable interface. By following the use of generic mechanisms introduced in J2SE 1.5, it can accurately control the type of cyclic variable that can be used. Moreover, because such a written code will be automatically used in the compilation period, it is not necessary to worry about the cost of exceeding performance. Reference resource You can find the SDK of the J2SE 1.5 and its documentation by Sun's Java Technology page. The latest version is currently J2SDK 1.5 Beta 2. Note When using this version of Javac, add "-Source 1.5" as a parameter to compile the source code for the new language characteristics in J2SE 1.5. John Zukowski introduced how to start using J2SDK 1.5 basics in "Tam Tiger: Tiger Preview". However, this article is written in accordance with the status of J2SDK 1.5 Alpha version, so some details (such as download address and default installation path) have changed. "JSR 201: Extending The Java Programming Language with Enumeration, Autoboxing, Enhanced for loops and static import" defines a lot of new language features in J2SE 1.5, including "Enhanced For loops because there is a second form" (Enhanced For loop ". "Java Collection API Design FAQ" explains why Java Collections Framework is designed to look like this, which is said to name the method in the java.util.ITerator interface. "JSR 14: adding generics to the java programming language" defines the generic mechanism in J2SE 1.5. Gilad Bracha In "Generics In The Java Programming Language", meticulous introduces the use of generic mechanisms in J2SE 1.5 and various restrictions. Calvin Austin In the article "J2SE 1.5 in a nutshell", Calvin Austin has a comprehensive and summary introduction to the new features in J2SE 1.5.