探秘JDK 7:将会出现新的语言特性

开发 后端
JDK 7本来在6月初将发布,但是Oracle把正式发布的时间推至今年秋天,JDK 7这个新版本将给我们带来很多的新特性,本文将给大家介绍JDK 7中新的语言特性,重点介绍二进制字面量,switch语句对字符串的支持和整型字面量下划线支持。

51CTO与所有的读者一样都在关注“Java 7”,曾经在6月4日跟踪报道“JDK 7发布情况”。本文***将从语言特性的角度与大家一起探讨一下JDK 7,看看JDK 会给***带来什么样的惊喜!

对JDK 7 的期待

Java平台***的主要版本是2006年12月发布的Java SE 6,经过近4年的开发,下一代Java平台将在今年与大家见面,根据OpenJDK功能列表的显示,以下功能将会包含在JDK 7中(最有可能被称为Java SE 7):

◆ 并发和集合更新;

◆ 椭圆曲线加密技术;

◆ 前向移植Java SE 6u10部署特性:Java内核,Quickstarter等;

◆ JAXB,JAXP和JAX-WS API升级;

◆ 新的语言特性:在任何Java类型上的注解,自动资源管理,二进制字面量,闭包,为模块化编程提供语言和虚拟机支持,switch语句支持字符串,泛型实例类型推断,整型字面量下划线支持等;

◆ 为Java SE 6u10图形功能提供了新的平台API:重量级/轻量级组件的混合,半透明和任意形状的窗口;

◆ 新的Swing组件:JXDatePicker,JXLayer装饰构件;

◆ Swing新的Nimbus外观;

◆ NIO.2(新的I/O,第二代);

◆ 在Solaris上支持套接字定向协议(Sockets Direct Protocol,SDP)和流控制传输协议(Stream Control Transmission Protocol,SCTP);

◆ Unicode 5.1支持;

◆ 升级了类加载器架构,包括了一个关闭URLClassLoader的方法;

◆ 虚拟机增强:压缩64位对象指针,新的G1垃圾回收器,对非Java语言的支持(InvokeDynamic);

◆ 为Java 2D提供的XRender管道。

除了等待今年晚些时候的JDK 7官方发布,你也可以在其早期版本中尝试其中的一些特性,可以去http://java.sun.com/javase/downloads/ea.jsp下载JDK 7第5个里程碑版本(目前***的版本)。

本文将重点介绍语言新特性中的二进制字面量,在switch中使用字符串和整型字面量下划线,我的环境是Windows XP SP3+JDK 7里程碑5版本,本文引用的示例代码可从http://www.informit.com/content/images/art_friesen_exploringjdk1/elementLinks/code.zip打包下载。

#p#

二进制字面量

Java从C/C++继承了用十进制(63),十六进制(0x3f)和八进制符号表示整型字面量,JDK 7也允许你增加0B或0b前缀用二进制符号表示整型字面量,如:

  1. int x = 0b10101111;  
  2. System.out.printf ("%d%n", x); // Output: 175  
  3.  

转换为二进制

java.util.Formatter类中的System.out.printf()方法提供了格式转换功能,你可以使用它将一个整数转换成十进制,十六进制和八进制符号,但它(仍然)不支持转换成二进制,必须借助整数的toBinaryString()方法进行转换:

  1. System.out.printf ("%s%n", Integer.toBinaryString (78));  
  2.  

这段代码将输出1001110,如果你希望Integer.toBinaryString()的输出结果包括首位的0(这在匹配列中二进制数字时非常有用),但不幸的是,这个方法不能满足你的愿望,必须再寻找另外的办法。

你可能会疑惑为什么二进制字面量怎么会包含在JDK 7中,据这个特性的创始人Derek Foster讲,使用按位运算的代码更具可读性,更容易验证使用二进制数字指定常量的技术规范,他同时指出,从心理上讲,从二进制转换成十六进制容易犯错。

当然,你也可以依赖整数的parseInt()方法将二进制数字字符串转换成整数,如Integer.parseInt ("00110011", 2)将返回51,但是,由于下列原因调用这个方法会有问题:

◆ 这个方法调用比直接使用字面量更冗长,它的调用语法极其凌乱;

◆ 这个方法调用会带来一定的性能损失;

◆ 编译器不能内联这个方法调用返回的值,但可以内联一个常量的值;

◆ 在字符串中检查到错误时,这个方法调用会抛出一个异常,我们在编译时才能捕获这个异常;

◆ 与二进制字面量不一样,不能使用switch语句的选择器值表示一个方法调用,如case Integer.parseInt ("00001110", 2):这样的语法是不正确的(也很丑陋),而case 0B00001110:这样的语法就是正确的(也易于阅读)。

#p#

在字符串上使用switch

在JDK 7中,switch语句进行了小幅升级,现在可以在字符串上使用switch了,你可以给switch语句提供一个字符串表达式,也可以给每个case提供一个常量字符串表达式,清单1是一个使用这个特性的WC(字数统计)程序的代码。

清单1 WC.java

  1. // WC.java  
  2. import java.io.IOException;  
  3. public class WC  
  4. {  
  5.    public static void main (String [] args) throws IOException  
  6.    {  
  7.       boolean caseInsensitive = false;  
  8.       boolean verbose = false;  
  9.       for (String arg: args)  
  10.            switch (arg)  
  11.            {  
  12.               case "-i":  
  13.               case "-I": caseInsensitive = true;  
  14.                          break;  
  15.                       
  16.               case "-V":  
  17.               case "-v": verbose = true;  
  18.                          break;  
  19.               default  : System.err.println ("usage  : "+  
  20.                                              "java WC [-i|-I -v|-V] stdin");  
  21.                          System.err.println ("example: java WC -v <WC.java");  
  22.                          return;  
  23.            }  
  24.       if (verbose)  
  25.           countWordsVerbose (caseInsensitive);  
  26.       else  
  27.           countWords ();  
  28.    }  
  29.    static void countWords () throws IOException  
  30.    {  
  31.       int ch, nWords = 0;  
  32.       while ((ch = System.in.read ()) != -1)  
  33.       {  
  34.          if (Character.isLetter (ch)) // Start of word is indicated by letter.  
  35.          {  
  36.              do  
  37.              {  
  38.                 ch = System.in.read ();  
  39.              }  
  40.              while (Character.isLetterOrDigit (ch));  
  41.              nWords++;  
  42.          }  
  43.       }  
  44.       System.out.println ("\nTotal words = " + nWords);  
  45.    }  
  46.    static void countWordsVerbose (boolean caseInsensitive) throws IOException  
  47.    {  
  48.       int ch;  
  49.       WordNode root = null;  
  50.       while ((ch = System.in.read ()) != -1)  
  51.       {  
  52.          if (Character.isLetter (ch)) // Start of word is indicated by letter.  
  53.          {  
  54.              StringBuffer sb = new StringBuffer ();  
  55.              do  
  56.              {  
  57.                 sb.append ((char) ch);  
  58.                 ch = System.in.read ();  
  59.              }  
  60.              while (Character.isLetterOrDigit (ch));  
  61.              if (root == null)  
  62.                  root = new WordNode (sb.toString ());  
  63.              else  
  64.                  root.insert (sb.toString (), caseInsensitive);  
  65.          }  
  66.       }  
  67.       display (root);  
  68.    }  
  69.    static void display (WordNode root)  
  70.    {  
  71.       // root == null when leaf node has been reached (or perhaps there are no  
  72.       // words in tree)  
  73.       if (root == null)  
  74.           return;  
  75.       // Display all words lexicographically less than the word in the current  
  76.       // node.  
  77.       display (root.left);  
  78.       // Display current node's word and number of occurrences.  
  79.       System.out.println ("Word = " + root.word + "Count = " +  
  80.                           root.count);  
  81.       // Display all words lexicographically greater than the word in the  
  82.       // current node.  
  83.       display (root.right);  
  84.    }  
  85. }  
  86. class WordNode  
  87. {  
  88.    String word;    // Stored word  
  89.    int count = 1;  // Number of occurrences of word in text  
  90.    WordNode left;  // Left subtree  
  91.    WordNode right; // Right subtree  
  92.    public WordNode (String word)  
  93.    {  
  94.       this.word = word;  
  95.       left = right = null;  
  96.    }  
  97.    public void insert (String word, boolean caseInsensitive)  
  98.    {  
  99.       int order = (caseInsensitive) ? this.word.compareToIgnoreCase (word)  
  100.                                     : this.word.compareTo (word);  
  101.       if (order > 0) // word argument lexicographically less than current  
  102.                      // word  
  103.       {  
  104.           // If left-most leaf node reached then insert new node as its  
  105.           // left-most leaf node; otherwise, keep searching left.  
  106.           if (left == null)  
  107.               left = new WordNode (word);  
  108.           else  
  109.               left.insert (word, caseInsensitive);  
  110.       }  
  111.       else  
  112.       if (order < 0) // word argument lexicographically greater than current  
  113.                      // word  
  114.       {  
  115.           // If right-most leaf node reached then insert new node as its  
  116.           // right-most leaf node; otherwise, keep searching right.  
  117.           if (right == null)  
  118.               right = new WordNode (word);  
  119.           else  
  120.               right.insert (word, caseInsensitive);  
  121.       }  
  122.       else  
  123.           this.count++; // Update number of found occurrences.  
  124.    }  
  125. }  
  126.  

#p#

上面的例子充分说明了处理命令行参数时在字符串上使用switch是很有用的,可以替代这个功能的是if-else if … else表达式,但这样一来会使代码更冗长。

编译好WC.java后,指定(-i或I,区分大小写)和(-v或-V,输出详细信息)命令行参数运行这个程序,如:

  1. java WC <WC.java        // Count the number of words in WC.java and report the total.  
  2. java WC -v <WC.java     // Count the number of occurrences of each word in WC.java and report   
  3.                         // each total.  
  4. java WC -i -v <WC.java  // Count the number of occurrences of each word in WC.java and report   
  5.                         // each total. Use a case-insensitive comparison so that, for example,   
  6.                         // this and This are treated as two occurrences of the same word instead   
  7.                         // of one occurrence each of two different words.  

整型字面量下划线

JDK 7支持数字下划线,改善了二进制,十进制,十六进制和八进制字面量的可读性,如:

  1. int mb_directory_info = 204_555_1212;  
  2. System.out.printf ("%d%n", mb_directory_info); // Output: 2045551212  
  3. long debt = 11_000_000_000_000L;  
  4. System.out.printf ("%d%n", debt); // Output: 11000000000000  
  5. byte max_pos_value = 0x0___07F;  
  6. System.out.printf ("%d%n", max_pos_value); // Output: 127  
  7.  

你可以在连续数字之间插入一到多个下划线,但不能在数字的最前面指定下划线(如_25这样是不允许的),因为这样将被解释为一个标识符,同样,也不能用下划线作为后缀(如0x3f_这样也是不允许的)。

虽然Foster提到Integer和Long的decode()方法将支持这个特性,但目前的版本还不支持,同样,Integer.parseInt()和Long.parseLong()也不支持这个特性。

小结

二进制字面量,switch对字符串的支持和整型字面量下划线支持仅仅是JDK 7新语言特性的一小部分,可以说它们是小而强大,但与闭包和模块化比起来,很多人可能会觉得它们微不足道。下一篇文章将会介绍起源于Java SE 6的半透明和任意形状的窗口的改进。

【编辑推荐】

  1. Java 7,一个技术标准的商业咒语
  2. JDK 7功能完备版今天发布?
  3. JDK 7一再延期的背景披露以及OpenJDK的尴尬
责任编辑:佚名 来源: IT168
相关推荐

2011-07-29 09:31:32

JDK 7

2011-05-20 09:35:22

JDK7

2011-05-20 09:43:23

JDK7

2010-06-28 09:26:15

JDK 7Swing组件Java

2011-05-20 10:15:06

JDK7

2011-05-20 09:53:00

JDK7

2011-05-20 10:28:29

JDK7

2011-05-20 10:20:11

JDK7

2011-05-20 09:59:42

JDK7

2009-11-23 19:50:12

PHP6.0

2014-11-26 10:23:09

2012-08-07 09:37:23

虚拟化

2017-08-08 10:30:50

物联网信息安全网络

2015-10-27 15:42:57

软件开发发展趋势

2021-05-06 20:03:00

JavaStream代码

2009-07-09 16:29:19

JDK版本

2015-10-23 11:35:00

软件开发发展趋势

2009-07-07 12:30:38

JDK1.6

2021-04-28 16:08:41

物联网趋势物联网IOT

2019-09-05 09:38:36

点赞
收藏

51CTO技术栈公众号