探秘JDK 7:將會(huì)出現(xiàn)新的語言特性
51CTO與所有的讀者一樣都在關(guān)注“Java 7”,曾經(jīng)在6月4日跟蹤報(bào)道“JDK 7發(fā)布情況”。本文***將從語言特性的角度與大家一起探討一下JDK 7,看看JDK 會(huì)給***帶來什么樣的驚喜!
對(duì)JDK 7 的期待
Java平臺(tái)***的主要版本是2006年12月發(fā)布的Java SE 6,經(jīng)過近4年的開發(fā),下一代Java平臺(tái)將在今年與大家見面,根據(jù)OpenJDK功能列表的顯示,以下功能將會(huì)包含在JDK 7中(最有可能被稱為Java SE 7):
◆ 并發(fā)和集合更新;
◆ 橢圓曲線加密技術(shù);
◆ 前向移植Java SE 6u10部署特性:Java內(nèi)核,Quickstarter等;
◆ JAXB,JAXP和JAX-WS API升級(jí);
◆ 新的語言特性:在任何Java類型上的注解,自動(dòng)資源管理,二進(jìn)制字面量,閉包,為模塊化編程提供語言和虛擬機(jī)支持,switch語句支持字符串,泛型實(shí)例類型推斷,整型字面量下劃線支持等;
◆ 為Java SE 6u10圖形功能提供了新的平臺(tái)API:重量級(jí)/輕量級(jí)組件的混合,半透明和任意形狀的窗口;
◆ 新的Swing組件:JXDatePicker,JXLayer裝飾構(gòu)件;
◆ Swing新的Nimbus外觀;
◆ NIO.2(新的I/O,第二代);
◆ 在Solaris上支持套接字定向協(xié)議(Sockets Direct Protocol,SDP)和流控制傳輸協(xié)議(Stream Control Transmission Protocol,SCTP);
◆ Unicode 5.1支持;
◆ 升級(jí)了類加載器架構(gòu),包括了一個(gè)關(guān)閉URLClassLoader的方法;
◆ 虛擬機(jī)增強(qiáng):壓縮64位對(duì)象指針,新的G1垃圾回收器,對(duì)非Java語言的支持(InvokeDynamic);
◆ 為Java 2D提供的XRender管道。
除了等待今年晚些時(shí)候的JDK 7官方發(fā)布,你也可以在其早期版本中嘗試其中的一些特性,可以去http://java.sun.com/javase/downloads/ea.jsp下載JDK 7第5個(gè)里程碑版本(目前***的版本)。
本文將重點(diǎn)介紹語言新特性中的二進(jìn)制字面量,在switch中使用字符串和整型字面量下劃線,我的環(huán)境是Windows XP SP3+JDK 7里程碑5版本,本文引用的示例代碼可從http://www.informit.com/content/images/art_friesen_exploringjdk1/elementLinks/code.zip打包下載。
#p#
二進(jìn)制字面量
Java從C/C++繼承了用十進(jìn)制(63),十六進(jìn)制(0x3f)和八進(jìn)制符號(hào)表示整型字面量,JDK 7也允許你增加0B或0b前綴用二進(jìn)制符號(hào)表示整型字面量,如:
- int x = 0b10101111;
- System.out.printf ("%d%n", x); // Output: 175
轉(zhuǎn)換為二進(jìn)制
java.util.Formatter類中的System.out.printf()方法提供了格式轉(zhuǎn)換功能,你可以使用它將一個(gè)整數(shù)轉(zhuǎn)換成十進(jìn)制,十六進(jìn)制和八進(jìn)制符號(hào),但它(仍然)不支持轉(zhuǎn)換成二進(jìn)制,必須借助整數(shù)的toBinaryString()方法進(jìn)行轉(zhuǎn)換:
- System.out.printf ("%s%n", Integer.toBinaryString (78));
這段代碼將輸出1001110,如果你希望Integer.toBinaryString()的輸出結(jié)果包括首位的0(這在匹配列中二進(jìn)制數(shù)字時(shí)非常有用),但不幸的是,這個(gè)方法不能滿足你的愿望,必須再尋找另外的辦法。
你可能會(huì)疑惑為什么二進(jìn)制字面量怎么會(huì)包含在JDK 7中,據(jù)這個(gè)特性的創(chuàng)始人Derek Foster講,使用按位運(yùn)算的代碼更具可讀性,更容易驗(yàn)證使用二進(jìn)制數(shù)字指定常量的技術(shù)規(guī)范,他同時(shí)指出,從心理上講,從二進(jìn)制轉(zhuǎn)換成十六進(jìn)制容易犯錯(cuò)。
當(dāng)然,你也可以依賴整數(shù)的parseInt()方法將二進(jìn)制數(shù)字字符串轉(zhuǎn)換成整數(shù),如Integer.parseInt ("00110011", 2)將返回51,但是,由于下列原因調(diào)用這個(gè)方法會(huì)有問題:
◆ 這個(gè)方法調(diào)用比直接使用字面量更冗長,它的調(diào)用語法極其凌亂;
◆ 這個(gè)方法調(diào)用會(huì)帶來一定的性能損失;
◆ 編譯器不能內(nèi)聯(lián)這個(gè)方法調(diào)用返回的值,但可以內(nèi)聯(lián)一個(gè)常量的值;
◆ 在字符串中檢查到錯(cuò)誤時(shí),這個(gè)方法調(diào)用會(huì)拋出一個(gè)異常,我們?cè)诰幾g時(shí)才能捕獲這個(gè)異常;
◆ 與二進(jìn)制字面量不一樣,不能使用switch語句的選擇器值表示一個(gè)方法調(diào)用,如case Integer.parseInt ("00001110", 2):這樣的語法是不正確的(也很丑陋),而case 0B00001110:這樣的語法就是正確的(也易于閱讀)。
#p#
在字符串上使用switch
在JDK 7中,switch語句進(jìn)行了小幅升級(jí),現(xiàn)在可以在字符串上使用switch了,你可以給switch語句提供一個(gè)字符串表達(dá)式,也可以給每個(gè)case提供一個(gè)常量字符串表達(dá)式,清單1是一個(gè)使用這個(gè)特性的WC(字?jǐn)?shù)統(tǒng)計(jì))程序的代碼。
清單1 WC.java
- // WC.java
- import java.io.IOException;
- public class WC
- {
- public static void main (String [] args) throws IOException
- {
- boolean caseInsensitive = false;
- boolean verbose = false;
- for (String arg: args)
- switch (arg)
- {
- case "-i":
- case "-I": caseInsensitive = true;
- break;
- case "-V":
- case "-v": verbose = true;
- break;
- default : System.err.println ("usage : "+
- "java WC [-i|-I -v|-V] stdin");
- System.err.println ("example: java WC -v <WC.java");
- return;
- }
- if (verbose)
- countWordsVerbose (caseInsensitive);
- else
- countWords ();
- }
- static void countWords () throws IOException
- {
- int ch, nWords = 0;
- while ((ch = System.in.read ()) != -1)
- {
- if (Character.isLetter (ch)) // Start of word is indicated by letter.
- {
- do
- {
- ch = System.in.read ();
- }
- while (Character.isLetterOrDigit (ch));
- nWords++;
- }
- }
- System.out.println ("\nTotal words = " + nWords);
- }
- static void countWordsVerbose (boolean caseInsensitive) throws IOException
- {
- int ch;
- WordNode root = null;
- while ((ch = System.in.read ()) != -1)
- {
- if (Character.isLetter (ch)) // Start of word is indicated by letter.
- {
- StringBuffer sb = new StringBuffer ();
- do
- {
- sb.append ((char) ch);
- ch = System.in.read ();
- }
- while (Character.isLetterOrDigit (ch));
- if (root == null)
- root = new WordNode (sb.toString ());
- else
- root.insert (sb.toString (), caseInsensitive);
- }
- }
- display (root);
- }
- static void display (WordNode root)
- {
- // root == null when leaf node has been reached (or perhaps there are no
- // words in tree)
- if (root == null)
- return;
- // Display all words lexicographically less than the word in the current
- // node.
- display (root.left);
- // Display current node's word and number of occurrences.
- System.out.println ("Word = " + root.word + ", Count = " +
- root.count);
- // Display all words lexicographically greater than the word in the
- // current node.
- display (root.right);
- }
- }
- class WordNode
- {
- String word; // Stored word
- int count = 1; // Number of occurrences of word in text
- WordNode left; // Left subtree
- WordNode right; // Right subtree
- public WordNode (String word)
- {
- this.word = word;
- left = right = null;
- }
- public void insert (String word, boolean caseInsensitive)
- {
- int order = (caseInsensitive) ? this.word.compareToIgnoreCase (word)
- : this.word.compareTo (word);
- if (order > 0) // word argument lexicographically less than current
- // word
- {
- // If left-most leaf node reached then insert new node as its
- // left-most leaf node; otherwise, keep searching left.
- if (left == null)
- left = new WordNode (word);
- else
- left.insert (word, caseInsensitive);
- }
- else
- if (order < 0) // word argument lexicographically greater than current
- // word
- {
- // If right-most leaf node reached then insert new node as its
- // right-most leaf node; otherwise, keep searching right.
- if (right == null)
- right = new WordNode (word);
- else
- right.insert (word, caseInsensitive);
- }
- else
- this.count++; // Update number of found occurrences.
- }
- }
#p#
上面的例子充分說明了處理命令行參數(shù)時(shí)在字符串上使用switch是很有用的,可以替代這個(gè)功能的是if-else if … else表達(dá)式,但這樣一來會(huì)使代碼更冗長。
編譯好WC.java后,指定(-i或I,區(qū)分大小寫)和(-v或-V,輸出詳細(xì)信息)命令行參數(shù)運(yùn)行這個(gè)程序,如:
- java WC <WC.java // Count the number of words in WC.java and report the total.
- java WC -v <WC.java // Count the number of occurrences of each word in WC.java and report
- // each total.
- java WC -i -v <WC.java // Count the number of occurrences of each word in WC.java and report
- // each total. Use a case-insensitive comparison so that, for example,
- // this and This are treated as two occurrences of the same word instead
- // of one occurrence each of two different words.
整型字面量下劃線
JDK 7支持?jǐn)?shù)字下劃線,改善了二進(jìn)制,十進(jìn)制,十六進(jìn)制和八進(jìn)制字面量的可讀性,如:
- int mb_directory_info = 204_555_1212;
- System.out.printf ("%d%n", mb_directory_info); // Output: 2045551212
- long debt = 11_000_000_000_000L;
- System.out.printf ("%d%n", debt); // Output: 11000000000000
- byte max_pos_value = 0x0___07F;
- System.out.printf ("%d%n", max_pos_value); // Output: 127
你可以在連續(xù)數(shù)字之間插入一到多個(gè)下劃線,但不能在數(shù)字的最前面指定下劃線(如_25這樣是不允許的),因?yàn)檫@樣將被解釋為一個(gè)標(biāo)識(shí)符,同樣,也不能用下劃線作為后綴(如0x3f_這樣也是不允許的)。
雖然Foster提到Integer和Long的decode()方法將支持這個(gè)特性,但目前的版本還不支持,同樣,Integer.parseInt()和Long.parseLong()也不支持這個(gè)特性。
小結(jié)
二進(jìn)制字面量,switch對(duì)字符串的支持和整型字面量下劃線支持僅僅是JDK 7新語言特性的一小部分,可以說它們是小而強(qiáng)大,但與閉包和模塊化比起來,很多人可能會(huì)覺得它們微不足道。下一篇文章將會(huì)介紹起源于Java SE 6的半透明和任意形狀的窗口的改進(jìn)。
【編輯推薦】