J2SE 1.5 新功能特性:新的For循环

原创 2005年06月01日 00:41:00
By Jeff Langr

Like many Java developers you are probably working with the beta for J2SE 1.5. Here is another new technique to use with the beta. Looping through a collection of objects and doing something with each object is one of the most common programming idioms. You've no doubt coded such a loop many times: 

  1. List names = new ArrayList();
  2. names.add("a");
  3. names.add("b");
  4. names.add("c");
  5. for (Iterator it = names.iterator(); it.hasNext(); ) {
  6.    String name = (String)it.next();
  7.    System.out.println(name.charAt(0));
  8. }


Instead of using a for loop, you might have used a while loop. You might have used an Enumeration, instead of an Iterator, if you were working with the older Vector class. Or, you might have used a for loop and a counter, accessing each element using the get(int index) method of the List interface. 

If you were to use an array, this is how you would typically iterate through each of its elements: 

  1. String[] moreNames = { "d""e""f" };
  2. for (int i = 0; i < moreNames.length; i++)
  3.    System.out.println(moreNames[i].charAt(0));



It's not difficult to iterate through a collection, but it is a very repetitive operation. Iteration requires you to type a good amount of characters. Granted, the template feature of most IDEs will eliminate your need to type so much. But, as you saw, there are many ways to iterate through a loop. 

The existence of several different iteration techniques costs you more time. For each iteration you encounter, you must spend a few extra seconds digesting the iteration form. If it deviates from the form you're used to seeing, you must examine it even closer. Why did the developer choose to code the iteration differently? 

It's also easy to make a mistake in coding your iterator. Ever accidentally coded something like this? 

  1. List names = new ArrayList();
  2. names.add("a");
  3. names.add("b");
  4. names.add("c");
  5. for (Iterator it = names.iterator(); it.hasNext(); ) {
  6.    String name = (String)it.next();
  7.    System.out.println(((String)it.next()).charAt(0));
  8. }


I have. In a small section of code, it's easy to spot the error. In a larger section of code, it's not as easy to spot. 

The foreach Loop


Java 1.5 introduces a new way of iterating over a collection of objects. The foreach loop is also known as the enhanced for loop. It is a new syntactical construct designed to simplify iteration. The foreach loop should make iteration more consistent, but only if and when everyone starts using it. 

Effective use of the foreach loop depends on using Java 1.5's parameterized types, also known as generics. So that you can understand the code in this article, I'll explain how to use parameterized types. 

Here is how you might construct and iterate a list of names in Java 1.5: 

List<String> names = new ArrayList<String>();
names.add("a");
names.add("b");
names.add("c");

for (String name: names)
   System.out.println(name.charAt(0));

There are two important things in this bit of code: first, the use of a generic list, and second, the use of the new foreach loop. 

To construct an object of the parameterized ArrayList type, you bind the ArrayList to a class. In the example, you bind the ArrayList to the String class. You also bind the List reference to the String class. You are now restricted to adding only String objects to the list. If you insert, for example, a Date object in the names collection, your code will not compile. When you retrieve objects from the list, you need not cast. Java knows that the list contains only String objects. It does the casting for you, behind the scenes. 

Once you have stored objects in a parameterized List, you can iterate through them using the foreach loop: 

for (String name: names)

You read this statement as, "for each String name in names." The Java VM executes the body of the foreach loop once for each object in the names collection. Each time through the loop, Java assigns the next object in turn to a local reference variable called name. You must declare this reference variable as a String type--the type to which you bound the names collection. 

The foreach loop is succinct. There is no need to cast; Java does the cast for you. You can use the name reference within the body of the loop as a String reference. You cannot use the name reference outside the body of the foreach loop. 

Using Foreach with Arrays


You saw how the foreach loop allows you to iterate over collection class types. Sun also modified Java to allow you to iterate through arrays using foreach. The syntax is exactly the same: 

  1. String[] moreNames = { "d""e""f" };
  2. for (String name: moreNames)
  3.    System.out.println(name.charAt(0));


Supporting Foreach in Your Own Class


Suppose you are building a Catalog class. A Catalog object collects any number of Product objects. You store these objects using an ArrayList instance variable defined in Catalog. Code working with a Catalog object will frequently need to iterate through the entire list of products, to do something with each object in turn. 

Here is how the Catalog class might look: 

  1. import java.util.*;
  2. class Catalog {
  3.    private List<Product> products = new ArrayList<Product>();
  4.    void add(Product product) {
  5.       products.add(product);
  6.    }
  7. }



The Product class includes a method that allows you to discount the price on a product: 

  1. class Product {
  2.    private String id;
  3.    private String name;
  4.    private BigDecimal cost;
  5.    Product(String id, String name, BigDecimal cost) {
  6.       this.id = id;
  7.       this.name = name;
  8.       this.cost = cost;
  9.    }
  10.    
  11.    void discount(BigDecimal percent) {
  12.       cost = cost.multiply(new BigDecimal("1.0").subtract(percent));
  13.    }
  14.    
  15.    public String toString() {
  16.       return id + ": " + name + " @ " + cost;
  17.    }
  18. }


A (Poor) Solution


To allow client code to work with all products, you could create a method in Catalog that returned the ArrayList of products: 

  1. // don't do this
  2. List<Product> getProducts() {
  3.    return products;
  4. }



Client code could iterate through the list however they chose. However, returning a collection to a client is a bad idea. By giving the client your collection, you have relinquished any control over the contents of that collection. Client code could add or remove elements to the collection without the knowledge of the Catalog object. You've also burdened the client with more work than necessary. 

The Iterable Interface


Instead, you can designate the Catalog class as being "iterable." Making a class iterable tells clients that they can iterate through its contents using a foreach loop. Sun has added to Java a new interface, java.lang.Iterable, that allows you to mark your classes as iterable: 

  1. package java.lang;
  2. import java.util.Iterator;
  3. public interface Iterable<T> {
  4.     Iterator<T> iterator();
  5. }


To implement this interface in Catalog, you must code an iterator method. This method must return an Iterator object that is bound to the Product type. 

The Catalog class stores all of its Product objects in an ArrayList. The easiest way to provide an Iterator object to a client is to simply return the Iterator object from the products ArrayList itself. Here is the modified Catalog class: 

  1. class Catalog implements Iterable<Product> {
  2.    private List<Product> products = new ArrayList<Product>();
  3.    void add(Product product) {
  4.       products.add(product);
  5.    }
  6.    
  7.    public Iterator<Product> iterator() {
  8.       return products.iterator();
  9.    }
  10. }


Note that the Iterator, the List reference, and the ArrayList are all bound to the Product type. 

Once you have implemented the java.lang.Iterable interface, client code can use the foreach loop. Here is a bit of example code: 
  1. Catalog catalog = new Catalog();
  2. catalog.add(new Product("1""pinto"new BigDecimal("4.99")));
  3. catalog.add(new Product("2""flounder"new BigDecimal("64.88")));
  4. catalog.add(new Product("2""cucumber"new BigDecimal("2.01")));
  5. for (Product product: catalog)
  6.    product.discount(new BigDecimal("0.1"));
  7.    
  8. for (Product product: catalog)
  9.    System.out.println(product);



Summary


The foreach loop provides a simple, consistent solution for iterating arrays, collection classes, and even your own collections. It eliminates much of the repetitive code that you would otherwise require. The foreach loop eliminates the need for casting as well as some potential problems. The foreach loop is a nice new addition to Java that was long overdue. I greatly appreciate the added simplicity in my source code. 

Trying it Out


You can download the current beta version of J2SE 1.5 from Sun's web site.

体验J2SE 1.5新特性之增强For循环

1.5提供了另一种形式的for循环。借助这种形式的for循环,可以用更简单地方式来遍历数组和Collection等类型的对象。本文介绍使用这种循环的具体方式,说明如何自行定义能被这样遍历的类,并解释和...
  • ergouge
  • ergouge
  • 2012年05月05日 00:02
  • 358

J2SE 1.5新特性之增强For循环

J2SE 1.5提供了另一种形式的for循环。借助这种形式的for循环,可以用更简单地方式来遍历数组和Collection等类型的对象。本文介绍使用这种循环的具体方式,说明如何自行定义能被这样遍历的类...
  • nengyu
  • nengyu
  • 2011年07月22日 17:01
  • 405

J2SE 1.5提供了另一种形式的for循环

J2SE 1.5提供了另一种形式的for循环。借助这种形式的for循环,可以用更简单地方式来遍历数组和Collection等类型的对象。本文介绍使用这种循环的具体方式,说明如何自行定义能被这样遍历的类...

ava SE 6 新特性: Instrumentation 新功能

006 年底,Sun 公司发布了 Java Standard Edition 6(Java SE 6)的最终正式版,代号 Mustang(野马)。跟 Tiger(Java SE 5)相比,Mustan...

Java SE 6 新特性: Instrumentation 新功能

Instrumentation 简介 利用 Java 代码,即 java.lang.instrument 做动态 Instrumentation 是 Java SE 5 的新特性,它把 Java...

用 J2SE1.5 建立多任务的Java应用程序

J2SE 5.0中的java.util.concurrent程序包提供了一个新的线程框架组件,这个框架组件处理了与建立、执行和管理线程相关的很多低层细节信息。在本文中我们将细致地了解一下它的重要特性。...

J2SE 1.5Varargs机制(Object... params)

http://blog.csdn.net/shihuan830619/article/details/6045339 J2SE 1.5提供了“Varargs”机制。借助这一机制,可以定义能和...

【J2SE归档总结】0x10 JDK1.5新特性

JDK1.5新特性: 泛型(Generics)为集合(collections)提供编译时类型安全,无需每刻从Collections取得一个对象就进行强制转换(cast) 增强的“for”循环(En...
  • WCG_BOY
  • WCG_BOY
  • 2012年12月17日 23:12
  • 326

[J2SE 1.5]逐渐挖掘Varargs(Object... params)

Object... params简单点来说就是说可以有任意多个Object类型的参数,也就是说可以传递0到多个Object类或子类的对象到这个方法。 转载地址:http://blog.csdn.ne...

黑马程序员_JAVA1.5新特性——高级For循环

---------------------- ASP.Net+Android+IO开发S、.Net培训、期待与您交流! ----------------------------------------...
  • redouba
  • redouba
  • 2013年07月07日 15:02
  • 767
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:J2SE 1.5 新功能特性:新的For循环
举报原因:
原因补充:

(最多只允许输入30个字)