一個程序員的爛筆頭兒

          記錄前進路上的每一個腳印

           

          轉載:jdk5.0新特性

          以下是網上摘錄的: JDK5.0的新特性(2005-2006)
          “JDK1.5”(開發代號猛虎)的一個重要主題就是通過新增一些特性來簡化開發,
          這些特性包括泛型,for-each 循環,自動裝包/拆包,枚舉,可變參數, 靜態導入
          C 風格的格式化 I/O、、并發實用程序以及更簡單的 RMI 接口生成。
          JSR 201 包括如下四個語言變化:增強的 for 循環、枚舉類型、靜態導入和 autoboxing;JSR 175 指定了新的元數據功能,而 JSR 14 則詳細說明了泛型。
          javac 編譯器執行的默認語言規范是版本 1.4。這意味著要利用以下語言變化的任何好處,需要向 javac 命令傳遞參數 -source 1.5。
          使用這些特性有助于我們編寫更加清晰,精悍,安全的代碼。
            下面我們簡單介紹一下這些新特性。
            1.泛型(Generic)
            C++通過模板技術可以指定集合的元素類型,而Java在1.5之前一直沒有相對應的功
          能。一個集合可以放任何類型的對象,相應地從集合里面拿對象的時候我們也不得不對
          他們進行強制得類型轉換。猛虎引入了泛型,它允許指定集合里元素的類型,這樣你可
          以得到強類型在編譯時刻進行類型檢查的好處。
           
          Collection c = new ArrayList();
          c.add(new Date());
           
            編譯器會給出一個錯誤:
           
          add(java.lang.String) in java.util.Collection cannot be applied to 
          (java.util.Date)
           
            2.For-Each循環
            For-Each循環得加入簡化了集合的遍歷。假設我們要遍歷一個集合對其中的元素進
          行一些處理。典型的代碼為:
           
          void processAll(Collection c){
              for(Iterator i=c.iterator(); i.hasNext();){
                  MyClass myObject = (MyClass)i.next();
                  myObject.process();
              }
          }
           
            使用For-Each循環,我們可以把代碼改寫成:
           
          void processAll(Collection c){
              for (MyClass  myObject :c)
                  myObject.process();
          }
           
            這段代碼要比上面清晰許多,并且避免了強制類型轉換。
            3.自動裝包/拆包(Autoboxing/unboxing)
            自動裝包/拆包大大方便了基本類型數據和它們包裝類地使用。
            自動裝包:基本類型自動轉為包裝類.(int >> Integer)
            自動拆包:包裝類自動轉為基本類型.(Integer >> int)
            在JDK1.5之前,我們總是對集合不能存放基本類型而耿耿于懷,現在自動轉換機制
          解決了我們的問題。
          int a = 3;
          Collection c = new ArrayList();
          c.add(a);//自動轉換成Integer.
          Integer b = new Integer(2);
          c.add(b + 2);
            這里Integer先自動轉換為int進行加法運算,然后int再次轉換為Integer.
            4.枚舉(Enums)
            JDK1.5加入了一個全新類型的“類”-枚舉類型。為此JDK1.5引入了一個新關鍵字
          enmu. 我們可以這樣來定義一個枚舉類型。
           
          public enum Color
          {
             Red,
             White,
             Blue
          }
            然后可以這樣來使用Color myColor = Color.Red.
            枚舉類型還提供了兩個有用的靜態方法values()和valueOf(). 我們可以很方便地
          使用它們,例如
          for (Color c : Color.values())
                      System.out.println(c);
            5.可變參數(Varargs)
            可變參數使程序員可以聲明一個接受可變數目參數的方法。注意,可變參數必須是
          函數聲明中的最后一個參數。假設我們要寫一個簡單的方法打印一些對象,
          util.write(obj1);
          util.write(obj1,obj2);
          util.write(obj1,obj2,obj3);
            在JDK1.5之前,我們可以用重載來實現,但是這樣就需要寫很多的重載函數,顯得
          不是很有效。如果使用可變參數的話我們只需要一個函數就行了
          public void write(Object... objs) {
             for (Object obj: objs)
                System.out.println(obj);
          }
            在引入可變參數以后,Java的反射包也更加方便使用了。對于
          c.getMethod("test", new Object[0]).invoke(c.newInstance(), new 
          Object[0])),現在我們可以這樣寫了
          c.getMethod("test").invoke(c.newInstance()),這樣的代碼比原來清楚了很多。 
            6.靜態導入(Static Imports)
            要使用用靜態成員(方法和變量)我們必須給出提供這個方法的類。使用靜態導入
          可以使被導入類的所有靜態變量和靜態方法在當前類直接可見,使用這些靜態成員無需
          再給出他們的類名。
          import static java.lang.Math.*;
          …….
          r = sin(PI * 2); //無需再寫r = Math.sin(Math.PI);
            不過,過度使用這個特性也會一定程度上降低代碼地可讀性。
          元數據
          J2SE 1.5 中的元數據特性提供這樣的能力,即向 Java 類、接口、方法和字段關聯附加的數據。這些附加的數據或者注釋,可以被 javac 編譯器或其他工具讀取,并且根據配置不同,可以被保存在類文件中,也可以在運行時使用 Java 反射 API 被發現。
          向 Java 平臺增加元數據的一個主要原因是,使得開發工具和運行工具有一個通用的基礎結構,以減少開發和部署所需的成本。工具可以使用元數據信息生成附加的源代碼,或者在調試時提供附加信息。
          下面的例子用元數據工具創建了一個調試元數據注釋,這些元數據注釋然后又簡單地在運行時顯示出來。可以想像,大部分的元數據標簽形成一個標準,即一個良好規范的集合。
          import java.lang.annotation.*;
          import java.lang.reflect.*;

          @Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @interface debug {
          boolean devbuild() default false;
          int counter();
          }

          public class MetaTest {
          final boolean production=true;
          @debug(devbuild=production,counter=1) public void testMethod() {
          }


          public static void main(String[] args) {

          MetaTest mt = new MetaTest();
          try {
          Annotation[] a = mt.getClass().getMethod("testMethod").getAnnotations();
          for (int i=0; i<a.length ; i++) {
          System.out.println("a["+i+"]="+a+" ");
          }
          } catch(NoSuchMethodException e) {
          System.out.println(e);
          }
          }
          }

          利用一個元數據處理工具,許多重復的代碼編寫步驟可以減少成一個簡練的元數據標簽。例如,訪問某個 JAX-RPC 服務實現時所需的遠程接口可以實現為:
          原來(J2SE 1.5 以前版本):
          public interface PingIF extends Remote {
          public void ping() throws RemoteException;
          }
          public class Ping implements PingIF {
          public void ping() {
          }
          }
           

          現在:
          public class Ping {
          public @remote void ping() {
          }
          }
          二、元數據(注解)
            這是JDK5.0學XDoclt的,有了注解,以后我們可以不必寫接口,EJB寫起來會方便很多。EJB3.0要精簡寫法,注解要占一些功勞。
            介紹一個常用的注解:@Override,示例如下:
          public class Test extends ATest{

          @Override
              public void test() {
              }
          }
           在方法前加了這個注解,就限定死了Test的這個方法一定要是覆蓋自ATest的方法test,否則就會報錯。比如你不心把方法test()寫成了tesd(),編譯時就會報錯。另一個要注意的是@Override用于定義覆蓋接口的方法,也就是說ATest必須是一個抽象類、普通類,但不能是接口。
             另一個常見到的注解是@Deprecated,表明該項(類、字段、方法)不再被推薦使用。不過我們自己一般很少用到這個注解。
            好了,注解只講這兩個吧,也不必了解太多,知道個概念,以后用到的時候再說吧。關于注解,建議看看XDoclt,這是一個開源小工具,在項目開發中非常好用。
          我喜愛的Java 5.0的五個特性
          作者:David Flanagan, Java in a Nutshell, 第5版的作者

          版權聲明:可以任意轉載,轉載時請務必以超鏈接形式標明文章原始出處和作者信息及本聲明
          作者:
          David Flanagan;xml1123
          原文地址:
          http://www.onjava.com/pub/a/onjava/2005/04/20/javaIAN5.html
          中文地址:
          http://www.matrix.org.cn/resource/article/43/43830_Java5.html
          關鍵詞: Java5

          至今,毫無疑問你已經看過不止一篇網上文章列舉了Java5.0的偉大的語言新特性:泛型,標注,枚舉類型,自動裝箱,可變參數, for/in循環,甚至靜態引入。我也認為這些是偉大的特性,但是,你已經讀過他們了。因此,在此我將集中于你可能沒有聽說過的Java5.0的新API特性。

          那么,在下面,是我喜歡的Java5.0的五個新API特性。我已經在《果殼中的Java》(《Java in a nut shell》)第五版的第五章中介紹過他們。并且我也在我的網站中記錄了其中的一些。那些看完本文后的細心的讀者會發現額外的獎勵—第六個特性:很少有人知道的Java5.0支持的新語言語法,當然使用者就更少了。我非常喜歡它,因為它很新異。

          Callable 和 Future 接口

          我喜歡的第一個特性發掘自新的java.util.concurrent包。如它的名字暗示的,這是個并行編程工具包。在此有很多要探索的,而我要提的第一喜歡的特性是TimeUnit枚舉類型。TimeUnit讓我感興趣的是它包含有用的時間相關工具--你通過一個枚舉常量來調用它們,該常量代表度量時間的單位。例如:
          TimeUnit.MILLISECONDS.sleep(200);

          然而,TimeUnit并不是最值得夸獎的。java.util.concurrent最強大的特性之一是它的任務-執行/線程-池結構。ExecutorService接口提供了執行任務的能力。Executors類定義了工廠方法用于獲取使用線程池的ExecutorService的實現。這是強大的要素。

          我所喜歡的任務-執行框架的部分是它如何表現任務以及執行它的結果:Callable和Future接口。我們都熟悉用于定義線程的Runnable接口和它的run()方法。Callable像Runnable,但它的方法叫做call(),并且這個方法可以返回一個結果或者拋出一個異常,而這兩點是Runnable.run()做不到的。

          Callable是一個泛型,并且它的結果已經參數化。例如,一個計算BigInteger的任務,是Callable<BigInteger>,并且它的方法call()被聲明為返回BigInteger。下面是僅有三行代碼的Callable接口:

          public interface Callable<V> {
                V call() throws Exception;
            }


          當我想要異步執行一個Callable任務,我將它傳遞給ExecutorService的submit()方法。submit()的返回值—這也是我喜歡的部分—是一個Future對象:本質上是一個對將來某時刻的結果的“借條”。如果我準備使用我的任務的結果,我簡單的調用Future對象的get()方法即可。如果任務的執行已完成,那么get()立刻返回結果。否則,它將阻塞直到結果可用。如果Callable拋出異常,那么get()方法將該異常包裝為ExecutionException并且拋出它。Future還有方法用來對任務的執行進行取消和查詢狀態,但是你必須自己查找它們(這些方法)。Future也用了泛型,并且結果的類型也參數化了。因此如果我submit()一個Callable<BigInteger>來執行,我將獲得一個Future< BigInteger >。

          下面是一個簡短的例子:

          /**
          * 這是一個用來計算大素數的Callable。
          */
          public class PrimeSearch implements Callable<BigInteger>
          {
              static Random prng = new SecureRandom();
              int n;
              public PrimeSearch(int bitsize) { n = bitsize; }
              public BigInteger call() {
                  return BigInteger.probablePrime(n, prng);
              }
          }

          // 嘗試同時計算兩個素數
          ExecutorService pool = Executors.newFixedThreadPool(2);
          Future<BigInteger> p = pool.submit(new PrimeSearch(512));
          Future<BigInteger> q = pool.submit(new PrimeSearch(512));

          // 將兩個素數相乘來得到一個合數
          BigInteger product = p.get().multiply(q.get());



          可變參數和自動裝箱

          我說過我不想談論Java5.0的新語言特性,我不會,但是我確實關注由于可變參數和自動裝箱才變為可能的(或者被增強的舊API)新的API。

          首先,當然,是Java5.0的printf風格的文本格式化能力,通過java.util.Formatter類和類似String.format()的工具方法。這類文本格式化是最常被引用來支持語言的增加的可變參數和自動裝箱的那種用例。考慮這個:

          String s = String.format("%s:%d: %s%n", filename,
                                     lineNumber,
                                       exception.getMessage());


          關于這段代碼沒有什么特別值得注意的東西。我將它列在這是為了說明因為可變參數和自動裝箱所以比下面的例子顯得簡單:

          String s = String.format("%s:%d: %s%n", new Object[] {
                                     filename,
                                     new Integer(lineNumber),
                                       exception.getMessage()});

          一、C風格格式化輸出
          在JDK5.0后,我們這樣寫代碼:
              public static void main(String[] args) {
                  int x = 10;
                  int y = 20;
                  int sum = x + y;
                  System.out.printf("%d + %d = %d", x, y, sum);
              }

          可變參數和自動裝箱還對java.lang.reflect API有一個實質性的影響。那就是當查找和調用方法時不再需要類和對象數組:

          Method m = c.getMethod("put", Object.class,Object.class);
            m.invoke(map, "key", "value");


          如果我必須選擇一個最喜歡的可變參數方法,那么,將是java.util.Arrays.asList()。這個方法真是個用于創建不變的對象列表的方便的工廠方法。它接受任何數量的類型T的參數并且將它們作為List<T>返回:

          List<Integer> smallPrimes =
               Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19);


          能力

          我們在上面談論了Runnable和Callable,并且你毫無疑問已經聽說過重要的Comparable, Serializable,和Cloneable接口。Java5.0新增加了五個重要的能力接口。第一個,當然,是java.lang.Iterable。你或許知道Java5.0新的for/in循環可以迭代數組和集合。你可能不知道它能夠對任何實現了可迭代(Iterable)接口的對象工作。因此,如果你想讓一個不是集合的數據結構可以簡單地迭代,只需實現Iterable接口。你要做的就是增加一個返回java.util.Iterator 的iterator()方法。當然,寫這個迭代器(Iterator)可能不是那么簡單的。

          下面的代碼是一個實現了Iterable<String>(是的,Iterable是泛型的)的文本文件類,因而允許文本文件可以用for/in循環逐行的迭代。你可以用類似下面的代碼使用它:

          TextFile textfile = new TextFile(new File(f), "UTF-8");
            int lineNumber = 0;
            for(String line : textfile)
                System.out.printf("%6d: %s%n", ++lineNumber, line);


          下面是TextFile的代碼。注意,迭代器不嘗試檢測對底層文件的并發的修改。如果你想自己做,看一看

          java.nio.channels.FileLock。
          import java.io.*;
          import java.util.Iterator;

          public class TextFile implements Iterable<String> {
              File f;
              String charsetName;

              public TextFile(File f, String charsetName)
                  throws IOException
              {
                  this.f = f;
                  this.charsetName = charsetName;

                  if (!f.exists())
                      throw new FileNotFoundException(f.getPath());
                  if (!f.canRead())
                      throw new IOException("Can't read: " +
                                            f.getPath());
              }

              public Iterator<String> iterator() {
                  try {
                      return new TextFileIterator(f, charsetName);
                  }
                  catch(IOException e) {
                      throw new IllegalArgumentException(e);
                  }
              }


              static class TextFileIterator
                  implements Iterator<String>
              {
                  BufferedReader in;
                  String nextline;
                  boolean closed = false;

                  public TextFileIterator(File f, String charsetName)
                      throws IOException
                  {
                      InputStream fis = new FileInputStream(f);
                      Reader isr =
                          new InputStreamReader(fis, charsetName);
                      in = new BufferedReader(isr);
                      getNextLine();
                  }

                  public boolean hasNext() {
                      return nextline != null;
                  }

                  public String next() {
                      String returnValue = nextline;
                      getNextLine();
                      return returnValue;
                  }

                  public void remove() {
                      throw new UnsupportedOperationException();
                  }

                  void getNextLine() {
                      if (!closed) {
                          try { nextline = in.readLine(); }
                          catch(IOException e) {
                              throw new IllegalArgumentException(e);
                          }
                          if (nextline == null) {
                              try { in.close(); }
                              catch(IOException ignored) {}
                              closed = true;
                          }
                      }
                  }
              }
          }


          Iterable是到目前為止最重要的新能力接口,但是其它的也是非常的漂亮。接下來,我們碰到java.lang.Appendable。一個Appendable對象可以追加字符或字符序列(或者一個字符序列的子序列)。實現者包括StringBuffer和StringBuilder(如果你還沒有聽說過它,一定要看一看),Writer(及其子類),PrintStream,還有java.nio.CharBuffer。將可追加性從這些類中分離出來成為Appendable接口,使得新的java.util.Formatter類更強大:它能將文本格式化為任何可追加的對象,包括你自己的實現。(練習留給讀者:你能否將上面的TextFile類變得既可迭代又可追加么?)。


          java.lang.Readable接口和Appendable相反:一個可讀對象可以將字符傳輸給給定的CharBuffer。java.io.Reader和它的全部子類都是可讀的(當然了),CharBuffer本身也一樣。就像Appendable是為了java.util.Formatter的利益而創造,Readable是為了java.util.Scanner的利益而創造。(Java5.0增加了Scanner,連同Formatter。這是Java對C的scanf()函數的適應,但是它(Scanner)不像Formatter之對應于printf()的關系那樣密切。)

          我想討論的最后兩個能力接口是java.io.Closeable和java.io.Flushable。如它們的名字暗示的,它們趨向于被任何類實現,通過一個close()或者flush()方法。Closeable被所有的輸入和輸出流類,RandomAccessFile和Formatter實現。Flushable被輸出流類和Formatter實現。這些接口也是為了Formatter類的利益而定義。注意,Appendable對象(像StringBuilder)不總是可關閉或者可沖刷(flushable)。通過將可關閉性和可沖刷性分解出來成為這些接口,Formatter的close()和flush()方法能夠決定它們操作的Appendable對象是否需要被關閉或被沖刷。(Java5.0還增加了第六個能力接口,并且它也是有關Formatter類的。那些想要控制它們的實例怎樣被格式化的類可以實現java.util.Formattable接口。然而這個接口的API是難用的,我不想談論它。)

          @Override

          毫無疑問,你已經聽說過能用元數據標注Java5.0的類型和方法。但是你可能不熟悉增加到java.lang的標準標注類型。我喜歡的第四個特性就是java.lang.Override標注。當你寫一個方法準備覆蓋另一個的方法時,用@Override來標注它,這樣編譯器會進行檢查來確保你確實,實際上,覆蓋了你想覆蓋的方法。

          如果你拼寫錯了方法名字或者弄錯了方法參數,那么你實際上并沒有覆蓋那個你認為你覆蓋了的方法。這樣就造成了一個如果不用@Override很難捕捉的臭蟲。我所以知道是因為我的關于Java1.4的新API特性的文章就講到了這個臭蟲,并且這個錯誤至少有一年一直沒被檢測到(至少沒有被報告)。在那篇文章中,你可以在第一頁結尾看到我犯的錯誤。那篇文章現在包含一個鏈接到我的博客入口,在那里我改正了這個臭蟲并且在代碼中增加了@Override聲明。

          MatchResult
          我喜歡的Java5.0的最后一個特性是java.util.regex.MatchResult。對于用于正則表達式的模式/匹配API我從來沒有真正非常滿意。Java5.0增加的MatchResult在讓我大大地更加滿意。當使用一個不太平凡的模式(Pattern),每次調用匹配者(Matcher)的find()方法會生成許多狀態:開始位置,結束位置,匹配的文本,同時還有模式的開始,結束,每個子表達式的文本。在Java5.0以前,你只能從Matcher獲取它們,通過在調用find()后再調用start(),end(),還有group(),如果需要的話。

          然而,到了Java5.0,你可以只調用toMatchResult()來獲取MatchResult對象再獲取全部的狀態,MatchResult對象可以保存并且可以以后再檢查。MatchResult像Matcher一樣有start(),end(),以及group()方法,并且,實際上,Matcher現在實現了MatchResult。
          這里是一個有用的返回MatchResult的方法:

          public static List<MatchResult> findAll(Pattern pattern,
                                                  CharSequence text)  {
              List<MatchResult> results =
                  new ArrayList<MatchResult>();
              Matcher m = pattern.matcher(text);
              while(m.find()) results.add(m.toMatchResult());
              return results;
          }


          還有使用這個方法的代碼:

          List<MatchResult> results = findAll(pattern, text);
          for(MatchResult r : results) {
              System.out.printf("Found '%s' at (%d,%d)%n",
                                r.group(), r.start(), r.end());
          }



          十六進制浮點數字面值

          我承諾談論Java5.0的最晦澀的新語言特性。這就是:十六進制格式的浮點常量!這里是奇異的詳情:一個十六進制符號的浮點常量以0X或者0x開頭。隨后的十六進制數字形成了數的基數。關鍵是這些數字可以包含一個小數點(一個十六進制小數點?)。在基數后面是指數,是必需的。十六進制浮點常量使用p或者P而不是e或者E來引入指數。(想一下“冪”來幫助記憶)。P或者P后面是指數,必須是一個十進制數,而不是十六進制數。而且這是個以二為根的指數,而不是以十為根。那就是,表示基數要乘以的2的冪。最后,整個常量可以跟隨一個f或者F來表示一個浮點常量,或者一個d或者D表示一個雙精度常量,就像一個十進制浮點數一樣。
          下面是一些例子:

          double x = 0XaP0;    // 10 * 2^0 = 10.0
            double y = 0XfP2D;   // 15 * 2^2 = 60.0
            float z  = 0Xf.aP1F; // (15 + 10/16ths) * 2^1 = 31.25f
            // 用十進制來打印
            System.out.printf("%f %f %f%n", x, y, z);
            // 用十六進制來打印
            System.out.printf("%a %a %a%n", x, y, z);


          為什么Sun要對語言做這些?5.0的發行說明說:
          為了允許特定浮點值實現精確及可預見的規范,十六進制符號可用于Float和Double的浮點字面值和字符串到浮點數的轉換方法中。

          這點是合理的。十進制小數像0.1是不能精確地用浮點格式表示的,并且如果你真的需要確切知道在一個浮點或者雙精度值中比特位是怎么設的,那么你真的想要一個十六進制字面值。例如,Float.MAX_VALUE的Javadoc指出最大的浮點值是0x1.fffffeP+127f。

          如果你知道并且喜歡IEEE-754浮點標準,那么十六進制浮點字段值或許是你喜歡的一個特性。我只是認為他們有趣。
          一 從xml中裝載屬性
           
          格式:

          <properties>
          <comment>Hi</comment>
          <entry key="id">1</entry>
          <entry key="name">rocie</entry>
          <entry key="email">rocie@sina.com</entry>
          </properties>

           
           
           
          通過以下方法加載:

          Properties prop = new Properties();
          FileInputStream fis =  new FileInputStream("d:/jdk5/properties/test.xml");
          prop.loadFromXML(fis);
          prop.list(System.out);
          System.out.println("Name: " + prop.getProperty("name"));

           
           
           
          將xml文件放在WEB-INF/classes/目錄下,可以防止對路徑的硬編碼

          InputStream is = PropertiesTest.class.getClassLoader().getResourceAsStream("rocie.xml");
          Properties ps = new Properties();
          ps.loadFromXML(is);
          System.out.println("name:"+ps.getProperty("name"));        

           
           
           
          通過以下方法保存:

          Properties prop = new Properties();
          prop.setProperty("id", "2");
          prop.setProperty("name", "彭大雙");
          prop.setProperty("email", "pds@dotraining.com");
          FileOutputStream fos = new FileOutputStream("d:/jdk5/properties/pds.xml");
          prop.storeToXML(fos, "彭大雙","gbk");
          fos.close();

           
           
           
          xml文件細節:

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
          <properties>
          <comment>Hi</comment>
          <entry key="id">1</entry>
          <entry key="name">rocie</entry>
          <entry key="email">rocie@sina.com</entry>
          </properties>

           
           
           
          DTD文件:

          <?xml version="1.0" encoding="UTF-8"?>
          <!-- DTD for properties -->
          <!ELEMENT properties ( comment?, entry* ) >
          <!ATTLIST properties version CDATA #FIXED "1.0">
          <!ELEMENT comment (#PCDATA) >
          <!ELEMENT entry (#PCDATA) >
          <!ATTLIST entry key CDATA #REQUIRED>

          注:?表示0或1;*表示0至無限;+表示至少一個
           
           
           
          二 并發集合
          問題:ConcurrentModificationExceptionfail-fast
           
           
          當遍歷一個Iterator時,如果該Iterator對應的List里的元素發生改變,則拋出這個異常。
          解決方法:java.util.concurrent
           
           
          用CopyOnWriteArrayList代替原來的ArrayList
          copy-on-write:這意味著如果有大量的讀(即 get() ) 和迭代,不必同步操作以照顧偶爾的寫(即 add() )調用。對于新的 CopyOnWriteArrayList 和 CopyOnWriteArraySet 類,所有可變的(mutable)操作都首先取得后臺數組的副本,對副本進行更改,然后替換副本。這種做法保證了在遍歷自身更改的集合時,永遠不會拋出 ConcurrentModificationException 。遍歷集合會用原來的集合完成,而在以后的操作中使用更新后的集合。
           
           
           
          用 for/in 在 Java 5.0 中增強循環

          public static List<Integer> list = new ArrayList<Integer>();
                
                 public static int[] is = new int[]{1,2,3,4,65,456};
                
                 static
                 {           
                        for(int i=0;i<100;i++)
                               list.add(i);             
                 }
                
                 public static void main(String args[])
                 {
                        for(Integer i:list)
                               System.out.println(i);    
                        System.out.println("-------other for each--------");
                        for(int i:is)
                               System.out.println(i);
                 }

          枚舉類型 enum

          public class EnumTest {
                 private Color color;
                
                 public static enum Color {red,yellow,blue,green};    
                
                 public Color getColor() {
                        return color;
                 }
           
           
           
                 public void setColor(Color color) {
                        this.color = color;
                 }
           
           
           
                 public static void main(String args[])
                 {
                        for(Color c:Color.values())
                        {
                               System.out.println("name:"+c.name()+"ordinal:"+c.ordinal());
                        }    
                        EnumTest et = new EnumTest();
                        et.setColor(Color.red);
                        Color c = et.getColor();
                        switch(c)
                        {
                        case red: System.out.println("red:"+c.name()+c.ordinal());
                                             break;
                        case yellow: System.out.println("yellow"+c.name()+c.ordinal());
                                             break;
                        default : System.out.println("over");
                        }
                       
                 }
          }
           
           

           
          并發實用程序
          并發實用程序庫由 Doug Lea 定義在 JSR-166 中,是 J2SE 1.5 平臺中流行的并發軟件包的一個特殊版本。它提供強大的、高級別的線程構造,包括 executors(這是一個線程任務框架)、線程安全隊列、Timers、鎖(包括原子鎖)和其他同步原語。
          著名的旗語(semaphore)是這樣一個鎖。旗語與現在使用的 wait 的使用方式相同,用于限制對一塊代碼的訪問。旗語更加靈活,并且也允許許多并發的線程訪問,同時允許您在獲得一個鎖之前對它進行測試。下面的例子使用剛好一個旗語,也叫做二進制旗語。更多信息請參見 java.util.concurrent 軟件包。
          final private Semaphore s= new Semaphore(1, true);
          s.acquireUninterruptibly(); //for non-blocking version use s.acquire()

          balance=balance+10; //protected value
          s.release(); //return semaphore token

          rmic —— rmi 編譯器
          您不再需要使用 rmic —— rmi 編譯器工具——來生成最遠程的接口存根。動態代理的引入意味著通常由存根提供的信息可以在運行時被發現。更多信息請參見 RMI 版本說明。
          可擴展性和性能
          1.5 版本承諾在可擴展性和性能方面的改進,新的重點在于啟動時間和內存占用,使它更加易于以最大的速度部署應用程序。
          最重大的一個更新是引入了 Hotspot JVM 中的類數據共享。該技術不僅在多個正在運行的 JVM 之間共享只讀數據,而且改進了啟動時間,因為核心的 JVM 類都是預先打包的。
          性能工效是 J2SE 1.5 中的一個新特性,這意味著如果您一直使用的是以前版本中專門的 JVM 運行時選項, 那么可能值得不用選項或者用很少的選項重新驗證您的性能。
          監控和可管理性
          監控和可管理性是 Java 平臺中的 RAS (Reliability, Availability, Serviceability,即可*性、可用性、可服務性) 的一個關鍵組件。
          JVM Monitoring & Management API (JSR-174) 指定一組全面的可以從正在運行的 JVM 進行監控的 JVM internals。 該信息可通過 JMX (JSR-003) MBeans 訪問到,也可以使用 JMX 遠程接口 (JSR-160) 和行業標準 SNMP 工具而遠程訪問得到。
          最有用的一個特性是一個低內存檢測程序。當超過閥值時,JMX MBeans 可以通知已注冊的偵聽程序。更多信息請參見 javax.management 和 java.lang.management。
          為了了解新的 API 是多么容易使用,下面報告了 Hotspot JVM 中內存堆的詳細使用情況。
          import java.lang.management.*;
          import java.util.*;
          import javax.management.*;
          public class MemTest {
          public static void main(String args[]) {
          List pools =ManagementFactory.getMemoryPoolMBeans();
          for(ListIterator i = pools.listIterator(); i.hasNext();) {
          MemoryPoolMBean p = (MemoryPoolMBean) i.next();
          System.out.println("Memory type="+p.getType()+" Memory usage="+p.getUsage());
          }
          }
          }

          新的 JVM profiling API (JSR-163)
          該版本還包含一個更強大的本機 profiling API,叫做 JVMTI。該 API 已經在 JSR 163 中指定了,并由對改善的 profiling 接口的需求所推動。但是,JVMTI 除了具有 profiling 功能之外,還想要涵蓋全范圍的本機內部過程工具訪問,包括監控工具、調試工具以及潛在的各種各樣的其他代碼分析工具。
          該實現包含一個用于字節碼裝置(instrumentation)——Java 編程語言裝置服務(Java Programming Language Instrumentation Services,JPLIS)的機制。這使得分析工具只在需要的地方添加額外的配置信息(profiling)。該技術的優點是,它允許更加集中的分析,并且限制了正在運行的 JVM 上的 profiling 工具的引用。該裝置甚至可以在運行時和類加載時動態地生成,并且可以作為類文件預先處理。
          下面這個例子創建了一個裝置鉤(instrumentation hook),它可以從磁盤加載類文件的一個已修改的版本。要運行該測試,可利用 java -javaagent:myBCI BCITest 啟動 JRE。

          //File myBCI.java
          import java.lang.instrument.Instrumentation;

          public class myBCI {
          private static Instrumentation instCopy;

          public static void premain(String options, Instrumentation inst) {
          instCopy = inst;
          }
          public static Instrumentation getInstrumentation() {
          return instCopy;
          }
          }

          //File BCITest.java

          import java.nio.*;
          import java.io.*;
          import java.nio.channels.*;
          import java.lang.instrument.*;

          public class BCITest {
          public static void main (String[] args) {
          try {
          OriginalClass mc = new OriginalClass();
          mc.message();

          FileChannel fc=new FileInputStream(new File("modified"+File.separator+"OriginalClass.class")).getChannel();
          ByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, (int)fc.size());
          byte[] classBuffer = new byte[buf.capacity()];
          buf.get(classBuffer, 0, classBuffer.length);
          myBCI.getInstrumentation().redefineClasses(new ClassDefinition[] {new ClassDefinition(mc.getClass(), classBuffer)});
          mc.message();
          }catch (Exception e){}
          }
          }

          //OriginalClass.java
          //Compile in current directory
          //Copy source to modified directory,change message and recompile

          public class OriginalClass {
          public void message() {
          System.out.println("OriginalClass");
          }
          }



          改進的診斷能力
          如果沒有控制臺窗口可用,生成的 Stack 跟蹤就很笨拙。兩個新的 API —— getStackTrace 和 Thread.getAllStackTraces —— 以程序的方式提供該信息。
          StackTraceElement e[]=Thread.currentThread().getStackTrace();
          for (int i=0; i <e.length; i++) {
          System.out.println(e);
          }
          System.out.println("\n"+Thread.getAllStackTraces());

          Hotspot JVM 包含一個致命的錯誤處理程序(error hander),如果 JVM 異常中斷,它可以運行用戶提供的腳本。使用 Hotspot JVM 可服務性代理連接器,調試工具也可以連接到一個掛起的 JVM 或者核心文件。
          -XX:OnError="command"
          -XX:OnError="pmap %p"
          -XX:OnError="gdb %p"
          optional %p used as process id

          桌面客戶端
          Java 桌面客戶端保留有 Java 平臺的一個關鍵組件,并且這一點成了 J2SE 1.5 中許多改進的焦點。
          這個 Beta 版本包含啟動時間和內存占用方面的一些早期改進。該版本不僅更快,并且 Swing 工具集采用了一個暫新的叫做 Ocean 的主題。
          通過建立 J2SE 1.4.2 中的更新,GTK 和 Windows XP 外觀方面有了更進一步的改進。

          Windows XP
          Click to Enlarge

          Linux/Redhat
          Click to Enlarge

          具有最新 OpenGL 驅動程序并且選擇了圖形卡的 Linux 和 Solaris 用戶,可以使用下面的運行時屬性從 Java2D 獲得本機硬件加速:
          java -Dsun.java2d.opengl=true -jar Java2D.
          Linux 版本也具有快速的 X11 Toolkit,叫做 XAWT,默認情況下是啟用的。如果您需要與 motif 版本進行比較,可以使用下面的系統屬性:
          java -Dawt.toolkit=sun.awt.motif.MToolkit -jar Notepad.jar
          (X11 Toolkit 叫做 sun.awt.X11.XToolkit)
          X11 Toolkit 也使用 XDnD 協議,所以您可以在 Java 和其他應用(比如 StarOffice 或 Mozilla)之間拖放簡單的組件。
          其他特性
          核心 XML 支持
          J2SE 1.5 引入了核心 XML 平臺的幾個修訂,包括 XML 1.1 和 Namespace、XML Schema、SAX 2.0.1、XSLT 和快速 XLSTC 編譯器,以及最后的 DOM 第 3 層支持。
          除了支持核心 XML 之外,未來版本的 Java Web Services Developer Pack 將交付最新的 Web 服務標準:JAX-RPC & SAAJ (WSDL/SOAP)、JAXB、XML Encryption and Digital Signature,以及用于注冊的 JAXR。
          輔助字符支持
          32 位的輔助字符支持作為傳輸到 Unicode 4.0 支持的一部分,已經慎重地添加到該平臺。輔助字符被編碼為一對特殊的 UTF16 值,以生成一個不同的字符或者碼點(codepoint)。一個代理對(surrogate pair)是一個高 UTF16 值和后面的一個低 UTF16 值的組合。這些高值和低值來自一個特殊范圍的 UTF16 值。
          一般來說,當使用 String 或者字符序列時,核心 API 庫將透明地為您處理新的輔助字符。但是因為 Java "char" 仍然保留為 16 位,所以非常少的一些使用 char 作為參數的方法,現在有了足夠的可以接受 int 值的方法,其中 int 值可以代表新的更大的值。特別是 Character 類,具有附加的方法來檢索當前的字符和接下來的字符,以便檢索輔助的碼點值,如下所示:
          String u="\uD840\uDC08";
          System.out.println(u+"+ "+u.length());
          System.out.println(Character.isHighSurrogate(u.charAt(0)));
          System.out.println((int)u.charAt(1));
          System.out.println((int)u.codePointAt(0));

          更多信息請參見 Character 中的 Unicode 部分。
          JDBC RowSets
          JDBC 行集支持有兩個主要的更新。CachedRowSet 包含從數據庫檢索的行的內存中的集合。但是它們也是不連接的,這意味著以后更新可以與數據庫重新同步。
          另一個組件是 WebRowSet,它使用數據庫行通過 XML 來傳輸數據。
          參考資料:
          New Language Features for Ease of Development in the Java 2 Platform, Standard Edition 1.5: http://java.sun.com/features/2003/05/bloch_qa.html
          Tiger Component JSRs
          003 Java Management Extensions (JMX) Specification http://jcp.org/en/jsr/detail?id=3
          013 Decimal Arithmetic Enhancement http://jcp.org/en/jsr/detail?id=13
          014 Add Generic Types To The Java Programming Language http://jcp.org/en/jsr/detail?id=14
          028 Java SASL Specification http://jcp.org/en/jsr/detail?id=28
          114 JDBC Rowset Implementations http://jcp.org/en/jsr/detail?id=114
          133 Java Memory Model and Thread Specification Revision http://jcp.org/en/jsr/detail?id=133
          160 Java Management Extensions (JMX) Remote API 1.0 http://jcp.org/en/jsr/detail?id=160
          163 Java Platform Profiling Architecture http://jcp.org/en/jsr/detail?id=163
          166 Concurrency Utilities http://jcp.org/en/jsr/detail?id=166
          174 Monitoring and Management Specification for the Java Virtual Machine http://jcp.org/en/jsr/detail?id=174
          175 A Metadata Facility for the Java Programming Language http://jcp.org/en/jsr/detail?id=175
          200 Network Transfer Format for Java Archives http://jcp.org/en/jsr/detail?id=200
          201 Extending the Java Programming Language with Enumerations, Autoboxing, Enhanced for Loops and Static Import http://jcp.org/en/jsr/detail?id=201
          204 Unicode Supplementary Character Support http://jcp.org/en/jsr/detail?id=204
          206 Java API for XML Processing (JAXP) 1.3 http://jcp.org/en/jsr/detail?id=206

          posted on 2007-06-22 10:49 BigMouse 閱讀(1372) 評論(0)  編輯  收藏 所屬分類: JAVA學習


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          導航

          統計

          留言簿(1)

          隨筆檔案(1)

          文章分類(1)

          文章檔案(1)

          友情鏈接

          最新隨筆

          搜索

          最新評論

          主站蜘蛛池模板: 阿荣旗| 荣成市| 连南| 玉门市| 甘德县| 建始县| 临沭县| 靖边县| 长汀县| 普定县| 搜索| 昌乐县| 桓台县| 新竹县| 高阳县| 潮安县| 墨竹工卡县| 虹口区| 淄博市| 嘉祥县| 上饶市| 永修县| 临漳县| 三原县| 廉江市| 平舆县| 古田县| 徐水县| 封开县| 海淀区| 大悟县| 积石山| 合川市| 托克托县| 吴旗县| 海林市| 招远市| 安阳市| 万源市| 吐鲁番市| 舒城县|