jhengfei
爱JAVA,爱生活

1 、重要的语言变化

l         泛型( Generics

l         增强型循环( foreach

l         自动封箱( Autoboxing )和解箱( Unboxing

l         安全类型的 Enums

l         Varargs

l         静态 import

l         Annotations

 

2 、泛型( Generics

1 )问题

l         从集合中获得元素时,必须进行类型转换:

Ø         类型转换是麻烦的

Ø         类型转换是不安全的,可能在运行时发生类型转换失败

l         为什么不能做的更好:告诉编译器集合中元素的类型?

Ø         让编译器加入类型转换功能

Ø         编译器会保证类型转换的成功

2 )过滤集合的例子

								
										// Removes 4-letter words from c; elements must be strings
								
						
								
										static void expurgate(Collection c) {
								
						
								
										
												       for (Iterator i = c.iterator(); i.hasNext();) {
								
						
								
										
												       
												       String s = (String) i.next();
								
						
								
										
												       
												       if (s.length() == 4) {
								
						
								
										
												         
												       i.remove();
								
						
								
										
												       
												       }
								
						
								
										
												       }
								
						
								
										}
								
						

3 )使用泛型

								
										// Removes 4-letter words from c
								
						
								
										static void expurgate(Collection
										<String>
										 c) {
								
						
								
										
												       for (Iterator
										<String>
										 i = c.iterator(); i.hasNext();) {
								
						
								
										
												       
												       if (i.next().length() == 4) {
								
						
								
										
												         
												       i.remove();
								
						
								
										
												       
												       }
								
						
								
										
												       }
								
						
								
										}
								
						

l         更加清晰和安全

l         没有类型转换、额外的括号和临时变量

l         提供编译时的类型检查

4)泛型不是模板

l         没有膨胀的代码

l         没有可怕的复杂性

l         没有模板元程序

l         简单的提供编译时类型安全性和消除类型转换

 

3、 增强型循环( foreach

1)问题

l         遍历集合是麻烦的事

l         Iterator通常只有在获取元素时才会用到

l         使用Iterator倾向于错误:

Ø         Iterator变量在循环中出现3次

Ø         使你有两次出错的机会

Ø         通常的拷贝粘贴错误

l         为什么不做的更好,如果能让编译器来为你处理Iterator?

2)通常访问集合元素的例子

								
										void cancelAll(Collection c) {
								
						
								
										
												       
										
										for (Iterator i = c.iterator(); i.hasNext();)
										 {
								
						
								
										
												       
												       TimerTask tt = (TimerTask) 
										i.next()
										;
								
						
								
										
												       
												       tt.cancel();
								
						
								
										
												       }
								
						
								
										}
								
						

3)使用增强循环的例子

								
										void cancelAll(Collection c) {
								
						
								
										
												       
										
										for (Object o : c)
										 {
								
						
								
										
												       
												       ((TimerTask) o).cancel();
								
						
								
										
												       }
								
						
								
										}
								
						

l         更加清晰和安全

l         Iterator无关

l         不可能使用错误的Iterator

4)结合泛型的例子

								
										void cancelAll(Collection
										<TimerTask>
										 c) {
								
						
								
										
												       for (TimerTask task : c) {
								
						
								
										
												       
												       task.cancel();
								
						
								
										
												       }
								
						
								
										}
								
						

l         更加简洁、清晰和安全

l         代码准确表达它所要做的

5)对数组同样适合

								
										//Returns the sum of the elements of a
								
						
								
										int sum(
										int[] a
										) {
								
						
								
										
												       int result = 0;
								
						
								
										
												       
										
										for (int i : a)
										 {
								
						
								
										
												       
												       result += i;
								
						
								
										
												       }
								
						
								
										
												       return result;
								
						
								
										}
								
						

l         消除使用数组索引的错误

l         具有前面所述的优点

6)灵活的嵌套Iterator

l         通常的例子

								
										List suits = ...;
								
						
								
										List ranks = ...;
								
						
								
										List sortedDeck = new ArrayList();
								
						
								
										// Broken - throws NoSuchElementException!
								
						
								
										for (Iterator i = suits.iterator(); i.hasNext();) {
								
						
								
										
												       for (Iterator j = ranks.iterator(); j.hasNext();) {
								
						
								
										
												       
												       sortedDeck.add(new Card(i.next(), j.next()));
								
						
								
										
												       }
								
						
								
										}
								
						
								
										// Fixed - a bit ugly
								
						
								
										for (Iterator i = suits.iterator(); i.hasNext();) {
								
						
								
										
												       Suit suit = (Suit) i.next();
								
						
								
										
												       for (Iterator j = ranks.iterator(); j.hasNext();) {
								
						
								
										
												       
												       sortedDeck.add(new Card(
										suit
										, j.next()));
								
						
								
										
												       }
								
						
								
										}
								
						

l         使用增强循环简单而灵活

								
										for (Suit suit : suits) {
								
						
								
										
												       for (Rank rank : ranks) {
								
						
								
										
												       
												       sortedDeck.add(new Card(suit, rank));
								
						
								
										
												       }
								
						
								
										}
								
						

 

4、 自动封箱( Autoboxing )和解箱( Unboxing

1 )问题

l         不能将int放入集合,必须使用Integer

l         在获取时转换回来又是麻烦的事

l         由编译器来做这些事不是更好吗?

2)使用通常方法创建一个频率表的例子

								
										public class Freq {
								
						
								
										
												       private static final Integer ONE = new Integer(1);
								
						
								
										 
								
						
								
										
												       public static void main(String[] args) {
								
						
								
										
												       
												       // Maps word (String) to frequency (Integer)
								
						
								
										
												       
												       Map m = new TreeMap();
								
						
								
										
												       
												       for (int i = 0; i < args.length; i++) {
								
						
								
										
												         
												       Integer freq = (Integer) m.get(args[i]);
								
						
								
										
												         
												       m.put(args[i], (freq == null ? 
										ONE : new Integer(
								
						
								
										
												         
												         
												       freq.intValue() + 1)))
										;
								
						
								
										
												       
												       }
								
						
								
										
												       
												       System.out.println(m);
								
						
								
										
												       }
								
						
								
										}
										
												
												
										
								
						

2)结合 自动封箱、泛型和增强循环的例子

								
										public class Freq {
								
						
								
										
												       public static void main(String[] args) {
								
						
								
										
												       
												       Map
										<String, Integer>
										 m = new TreeMap
										<String, Integer>
										();
								
						
								
										
												       
												       for (
										String word : args
										) {
								
						
								
										
												         
												       Integer freq = m.get(word);
								
						
								
										
												         
												       m.put(word, (freq == null ? 
										1 : freq + 1
										));
								
						
								
										
												       
												       }
								
						
								
										
												       
												       System.out.println(m);
								
						
								
										
												       }
								
						
								
										}
								
						

 

5、安全类型的 Enums

1)标准的int Enum模式

								
										public class Almanac {
								
						
								
										
												       public static final int SEASON_WINTER = 0;
								
						
								
										
												       public static final int SEASON_SPRING = 1;
								
						
								
										
												       public static final int SEASON_SUMMER = 2;
								
						
								
										
												       public static final int SEASON_FALL = 3;
								
						
								
										
												        ... // Remainder omitted
								
						
								
										}
								
						

l         缺点:

Ø         不是安全类型

Ø         没有名字空间:必须要有常量前缀

Ø         脆弱性:常量被编译到客户程序中

Ø         打印出的值不提供信息

2)安全类型的Enum模式的例子

								
										import java.io.Serializable;
								
						
								
										import java.util.Arrays;
								
						
								
										import java.util.Collections;
								
						
								
										import java.util.List;
								
						
								
										 
								
						
								
										public final class Season implements Comparable, Serializable {
								
						
								
										 
								
						
								
										
												       private final String name;
								
						
								
										 
								
						
								
										
												       public String toString() {
								
						
								
										
												       
												       return name;
								
						
								
										
												       }
								
						
								
										 
								
						
								
										
												       private Season(String name) {
								
						
								
										
												       
												       this.name = name;
								
						
								
										
												       }
								
						
								
										 
								
						
								
										
												       public static final Season WINTER = new Season("winter");
								
						
								
										
												       public static final Season SPRING = new Season("spring");
								
						
								
										
												       public static final Season SUMMER = new Season("summer");
								
						
								
										
												       public static final Season FALL = new Season("fall");
								
						
								
										 
								
						
								
										
												       private static int nextOrdinal = 0;
								
						
								
										
												       private final int ordinal = nextOrdinal++;
								
						
								
										 
								
						
								
										
												       public int compareTo(Object o) {
								
						
								
										
												       
												       return ordinal - ((Season) o).ordinal;
								
						
								
										
												       }
								
						
								
										 
								
						
								
										
												       private static final Season[] PRIVATE_VALUES = { WINTER, SPRING, SUMMER,
								
						
								
										
												         
												       FALL };
								
						
								
										 
								
						
								
										
												       public static final List VALUES = Collections.unmodifiableList(Arrays
								
						
								
										
												         
												       .asList(PRIVATE_VALUES));
								
						
								
										 
								
						
								
										
												       private Object readResolve() {
								
						
								
										
												       
												       // Canonicalize
								
						
								
										
												       
												       return PRIVATE_VALUES[ordinal];
								
						
								
										
												       }
								
						
								
										}
								
						

l         基本想法:使用导出自定义类型的常量,不提供public构造方法

l         修正上面所有的缺点

l         其它优点:

Ø         能够添加任意的方法、域变量

Ø         能够实现接口

l         缺点:

Ø         代码冗长

Ø         容易出错:每个常量出现3次

Ø         不能在switch语句中使用

l         为什么不能做的更好,由编译器来处理?

3)安全类型的Enum结构

l         编译器支持安全类型的Enum模式

l         类似典型的Enum(就象C、C++)

Ø         enum Season { WINTER, SPRING, SUMMER, FALL }

l         更大强大:

Ø         安全类型的Enum模式的所有优点

Ø         能够在switch语句中使用

4)结合泛型和增强循环的Enum例子

								
										enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }
								
						
								
										enum Rank { DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, 
								
						
								
										
												       EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }
								
						
								
										List<Card> deck = new ArrayList<Card>();
								
						
								
										for (Suit suit : Suit.values()) {
								
						
								
										
												       for (Rank rank : Rank.values()) {
								
						
								
										
												       
												       deck.add(new Card(suit, rank));
								
						
								
										
												       }
								
						
								
										}
								
						
								
										Collections.shuffle(deck);
								
						

5)有域变量、方法和构造方法的Enum例子

								
										public enum Coin {
								
						
								
										
												       PENNY(1), NICKEL(5), DIME(10), QUARTER(25);
								
						
								
										
												       
												
												
										
								
						
								
										
												       Coin(int value) {
								
						
								
										
												       
												       this.value = value;
								
						
								
										
												       }
								
						
								
										 
								
						
								
										
												       private final int value;
								
						
								
										 
								
						
								
										
												       public int value() {
								
						
								
										
												       
												       return value;
								
						
								
										
												       }
								
						
								
										}
								
						

l         使用Coin的例子:

								
										public class CoinTest {
								
						
								
										
												       public static void main(String[] args) {
								
						
								
										
												       
												       for (Coin c : Coin.values()) {
								
						
								
										
												         
												       System.out.println(c + ": \t" + c.value() + "¢ \t" + color(c));
								
						
								
										
												       
												       }
								
						
								
										
												       }
								
						
								
										 
								
						
								
										
												       private enum CoinColor {
								
						
								
										
												       
												       COPPER, NICKEL, SILVER
								
						
								
										
												       }
								
						
								
										 
								
						
								
										
												       private static CoinColor color(Coin c) {
								
						
								
										
												       
												       switch (c) {
								
						
								
										
												       
												       case PENNY:
								
						
								
										
												         
												       return CoinColor.COPPER;
								
						
								
										
												       
												       case NICKEL:
								
						
								
										
												         
												       return CoinColor.NICKEL;
								
						
								
										
												       
												       case DIME:
								
						
								
										
												       
												       case QUARTER:
								
						
								
										
												         
												       return CoinColor.SILVER;
								
						
								
										
												       
												       default:
								
						
								
										
												         
												       throw new AssertionError("Unknown coin: " + c);
								
						
								
										
												       
												       }
								
						
								
										
												       }
								
						
								
										}
								
						

 

6、 Varargs

1)问题

l         编写具有任意数量参数的方法,必须使用数组

l         创建和初始化数组是麻烦的事

l         如果由编译器来实现不是更好?

l         就象printf的基本用法一样

2)使用java.text.MessageFormat的例子

								
										Object[] arguments = {
								
						
								
										
												       new Integer(7),
								
						
								
										
												       new Date(),
								
						
								
										
												       "a disturbance in the Force"
								
						
								
										};
								
						
								
										String result = MessageFormat.format(
								
						
								
										
												       "At {1,time} on {1,date}, there was {2} on planet "
								
						
								
										
												       + "{0,number,integer}.", arguments);
								
						

3)使用 Varargs 的例子

								
										String result = MessageFormat.format(
								
						
								
										
												       At {1,time} on {1,date}, there was {2} on planet "
								
						
								
										
												       + "{0,number,integer}.",
								
						
								
										
												       
										
										7
										, new Date(), "a disturbance in the Force");
								
						

l         format方法的 Varargs 声明如下:

								
										public static String format(String pattern,
								
						
								
										
												         
												       
												       
										
										Object... arguments
										)
								
						

l         参数类型是Object[]

l         调用者不需要使用 Varargs 语法

 

7、 静态 import

1)使用类导出常量的例子

								
										public class Physics {
								
						
								
										
												       public static final double AVOGADROS_NUMBER = 6.02214199e23;
								
						
								
										
												       public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
								
						
								
										
												       public static final double ELECTRON_MASS = 9.10938188e-31;
								
						
								
										}
										
												
												
										
								
						

l         客户程序需要使用限定来访问常量:

								
										double molecules = 
										Physics.AVOGADROS_NUMBER
										 * moles;
								
						

2)避免限定的错误方法

								
										// 
										"Constant Interface" antipattern - do not use!
										
												
												
										
								
						
								
										public 
										interface
										 Physics {
								
						
								
										
												       public static final double AVOGADROS_NUMBER = 6.02214199e23;
								
						
								
										
												       public static final double BOLTZMANN_CONSTANT = 1.3806503e-23;
								
						
								
										
												       public static final double ELECTRON_MASS = 9.10938188e-31;
								
						
								
										}
								
						
								
										 
								
						
								
										public class Guacamole 
										implements Physics
										 {
								
						
								
										
												       public static void main(String[] args) {
								
						
								
										
												       double moles = ...;
								
						
								
										
												       double molecules = 
										AVOGADROS_NUMBER
										 * moles;
								
						
								
										
												        ...
								
						
								
										}
								
						

l         存在的问题:

Ø         滥用接口:不是用来定义类型的

Ø         实现细节污染导出API

Ø         使客户程序混乱

Ø         创建长期的承诺

Ø         如果编译器让我们避免限定名字不是更好吗?

3)解决:静态import

l         类似包的导入

l         导入类的静态成员

l         可以单个也可以全部导入

l         使用静态import的例子:

								
										import static org.iso.Physics.*;
								
						
								
										public class Guacamole {
								
						
								
										
												       public static void main(String[] args) {
								
						
								
										
												       
												       double molecules = 
										AVOGADROS_NUMBER
										 * moles;
								
						
								
										
												       
												       ...
								
						
								
										
												       }
								
						
								
										}
								
						

4)导入方法的例子(Math类)

l         替代

								
										x = Math.cos(Math.PI * theta);
								
						

成:

								
										x = cos(Math.PI * theta);
								
						

5)和Enum一起工作

								
										import static gov.treas.Coin.*;
								
						
								
										class MyClass {
								
						
								
										
												       public static void main(String[] args) {
								
						
								
										
												       
												       int twoBits = 2 * QUARTER.value();
								
						
								
										
												       
												       ...
								
						
								
										
												       }
								
						
								
										}
								
						

 

8、元数据( Annotations

1)问题

l         许多API需要相当数量的样板文件,如JAX-RPC Web服务需要成对的接口和实现

l         如果能够注视代码,使得工具能够生成样板文件不是更好?

l         许多API需要附加的文件来进行维护,如Bean需要BeanInfo类文件

l         如果能够注视代码,使得工具能够生成这些附加文件不是更好?

2)JAX-RPC Web服务的例子

								
										public interface CoffeeOrderIF extends java.rmi.Remote {
								
						
								
										
												       public Coffee [] getPriceList()
								
						
								
										
												       
												       throws java.rmi.RemoteException;
								
						
								
										
												       public String orderCoffee(String name, int quantity)
								
						
								
										
												       
												       throws java.rmi.RemoteException;
								
						
								
										}
								
						
								
										public class CoffeeOrderImpl implements CoffeeOrderIF {
								
						
								
										
												       public Coffee [] getPriceList() {
								
						
								
										
												       
												       ...
								
						
								
										
												       }
								
						
								
										
												       public String orderCoffee(String name, int quantity) {
								
						
								
										
												       
												       ...
								
						
								
										
												       }
								
						
								
										}
								
						

3)使用 Annotations 的例子

								
										import javax.xml.rpc.*;
								
						
								
										public class CoffeeOrder {
								
						
								
										
												       
												@Remote public Coffee [] getPriceList() {
								
						
								
										
												       
												       ...
								
						
								
										
												       }
								
						
								
										
												       
												@Remote public String orderCoffee(String name, int quantity) {
								
						
								
										
												       
												       ...
								
						
								
										
												       }
								
						
								
										}
								
						
posted on 2006-06-02 17:21 点滴铸就辉煌 阅读(445) 评论(0)  编辑  收藏 所属分类: 技术点滴

只有注册用户登录后才能发表评论。


网站导航: