zoukankan      html  css  js  c++  java
  • java1.5新特性(转)


    语法改动比较大的是泛型编程。使用泛型编程需要在声明的时候提供附加的声明信息。比如:
    List words =
    new ArrayList();
    需要替换成:
    List<String> words = new
    ArrayList<String>();
    这样做的一个优点是,如果你插入数组的数据类型不是字符串的话,你就可以在编译的时候发现和解决这个bug。如果不使用上面的声明,这个bug不可能在编译的时候发现,程序运行后会出现ClassCastException
    的错误。
    另一个好处是:你不在需要担心集合中的元素超出了范围:
    String title = ((String)
    words.get(i)).toUppercase();
    使用:
    String title =
    words.get(i).toUppercase();
    你能简单的介绍一下这些J2SE 1.5中改变最大的六个方面吗?
    好的,
    • 泛型编程
    – 提供集合对象的编译时安全类型检查。
    • 增强 for 循环 - 编程更容易,去掉了修正了导致迭代出错的问题。
    • 装箱/拆箱 -
    原始类型(int)和封装类型(Integer)的转换更容易。
    • 类型安全的枚举 – 提供了最常使用的类型安全的枚举模式。(Effective Java,
    Item 21)
    • 静态导入Static import - Lets you avoid qualifying static members with
    class names, without the shortcomings of the Constant Interface antipattern
    (Effective Java, Item 17).
    • Metadata –
    避免编写描述信息的代码,实现“声明”编程的模式。程序员声明需要做什么,然后由相关的工具来完成具体的工作。


    一、泛型编程:
    比如,过滤一个集合中的元素,现在的做法和j2se1.5中的做法有什么不同呢?
    现在的做法是:
    /**
    *
    从一个指定的集合中去掉一个4个字符的元素。
    */
    static void expurgate(Collection c) {
    for
    (Iterator i = c.iterator(); i.hasNext(); ) {
    String s = (String)
    i.next();
    if(s.length() ==
    4)
    i.remove();
    }}
    上面的代码,有些缺陷,在运行的过程中可能出错。比如:在集合中如果包含一个StringBuffer类型的数据。
    以后可以这样做:
    static
    void expurgate(Collection<String> c) {
    for (Iterator<String> i =
    c.iterator(); i.hasNext(); )
    if (i.next().length() ==
    4)
    i.remove();
    }
    二、增强的for循环!
    一个集合中元素的迭代,原来的做法繁琐。J2SE1.5中大多数情况下你不需要使用Iterate
    来遍历一个集合。增强的for循环,让编译器来完成具体的迭代工作。比如:
    void cancelAll(Collection c) {
    for
    (Iterator i = c.iterator(); i.hasNext(); ) {
    TimerTask tt = (TimerTask)
    i.next();
    tt.cancel();
    }
    }
    现在可以这样做:
    void cancelAll(Collection c)
    {
    for (Object o :
    c)
    ((TimerTask)o).close();
    }
    注意:上面的冒号,它表示:in。在C#中或者很自然的一个替代是:foreach
    和in
    。但是考虑到兼容性,我们没有那样做。
    泛型编程和增强的for结合后会是什么结果呢?
    上面的例子中的代码,可以用下面的代码表示:
    void
    cancelAll(Collection<TimerTask> c) {
    for (TimerTask task :
    c)
    task.cancel();
    }
    三、什么是装箱?
    大家知道,java语言中有两种数据类型:一些是基本数据类型,另一些是对象引用类型。基本的数据类型无法直接放入到集合中,除非做相应的类型转换。这种转换非常枯燥。
    举例:map数据类型的key用来存储单词,value用来存储单词重复的次数。这是一个计算单词出现频率的小程序。
    public
    class Freq {
    private static final Integer ONE = new Integer(1);
    public
    static void main(String args[]) {
    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);
    }
    }
    下面是采用装箱,泛型,和增强的for循环后的代码:
    public
    class Freq {
    public static void main(String args[]) {
    Map<String,
    Integer> m = new TreeMap<String, Integer>();
    for (String word :
    args)
    m.put(word, m.get(word)
    1);
    System.out.println(m);
    }
    }
    需要注意:上面的程序假定拆箱为null的时候,值为0。


    J2SE1.5的新特点(下)
    类型安全的枚举比以前的枚举有什么优点呢?
    有如下特点:

    提供编译时int枚举的安全检查,同时不再提供其他类型安全检查。
    • 提供了枚举的命名空间
    • 可以直接把它们放到集合中。

    因为他们本质上是类,你可以向里面添加属性和方法。
    上面的这些特点的确不错。能讲讲类型安全的枚举语言的特点和类型安全的枚举模式的关系吗?
    一般来说:上面的那些特点简单的从语义上支持了模式。看下面的例子,和C/C++
    枚举的声明很相似:
    enum Season { winter, spring, summer, fall
    }
    声明虽然相似,但是确让编译器实现了上面提到的许多特性。你还可以把Season用到switch的判断语句中。
    请举例说明“类型安全的枚举”的优点。
    下面是一个表示美分枚举类型的例子。
    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;
    }
    }
    这是个创举。我们定义了value来作为读取Coin的公共变量。在枚举的构造函数中可以在声明枚举实例的时候来初始化它。
    让我们看看进一步使用这个枚举的例子。
    我把不的呢。下面的程序打印一个表格和其中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 Coin.penny:   return
    CoinColor.copper;
    case Coin.nickel: return CoinColor.nickel;
    case
    Coin.dime:
    case Coin.quarter: return CoinColor.silver;
    default: throw new
    AssertionError("Unknown coin: " + c);
    }
    }
    }
    太棒了。那么静态引入static import
    的功能对程序员有什么帮助呢?
    首先他避免了程序员使用前缀的静态成员。以前常见的的一个替代的做法是:
    // "Constant Interface"
    antipattern – 不推荐的做法
    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;
    ...
    }
    }
    上面的做法达到了效果,可是却违背了一些设计原则。接口是用来定义方法和类型的,不是提供常量声明的。而且只是由Guacamole使用的常量也暴露给了使用其的客户端。
    静态引入功能提供了一个简单的实现。这个功能和包的import功能类似。
    import
    static org.iso.Physics.*;


    class Guacamole {
    public static void main(String[]
    args) {
    double molecules = AVOGADROS_NUMBER *
    moles;
    ...
    }
    }
    明白,那么什么是元数据类型metadata的功能呢?
    使用metadata和第三方工具提供商可以让程序员自己的日子好过点。
    以前许多发布API需要大量的描述信息。比如:定义一个JAX-RPC
    网络服务API你需要提供其接口和实现类。如下:
    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)
    {
    ...
    }
    }
    使用元数据功能,你可以节省大量的工作。你所需要做的是在代码上加上特殊的注释。你所使用的开发工具可是使用这些注释自动生成相关的代吗。如下所示:
    import
    javax.xml.rpc.*;


    public class CoffeeOrder {
    @Remote public Coffee []
    getPriceList() {
    ...
    }
    @Remote public String orderCoffee(String name,
    int quantity) {
    ...
    }
    }

  • 相关阅读:
    Android 创建Library Project(库项目)与引用操作
    Android插件化(二):使用DexClassLoader动态载入assets中的apk
    洛谷P3388 【模板】割点(割顶)(tarjan求割点)
    BZOJ 1179: [Apio2009]Atm(tarjan+SPFA)
    洛谷P1067 多项式输出(模拟)
    洛谷P2118 比例简化(暴力)
    BZOJ 3714: [PA2014]Kuglarz(最小生成树)
    BZOJ 4289: PA2012 Tax(最短路)
    BZOJ 4152: [AMPPZ2014]The Captain(最短路)
    洛谷P2939 [USACO09FEB]改造路Revamping Trails(最短路)
  • 原文地址:https://www.cnblogs.com/mshwu/p/2667159.html
Copyright © 2011-2022 走看看