bomberlhl

          導航

          <2009年12月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          隨筆檔案

          統計

          留言簿(1)

          閱讀排行榜

          評論排行榜

          2009年12月1日 #

          【轉】使用synchronized進行Java線程同步

          線程同步指多個線程同時訪問某資源時,采用一系列的機制以保證同時最多只能一個線程訪問該資源。
          為什么需要線程同步呢?
          我們舉一個最簡單的例子來說明為什么需要線程同步。
          比如有一本書(有且只有一本),交給多個售貨員同時去賣;
          如果其中任何一個售貨員把這本書給賣了,其他售貨員就不能再賣這本書了。
          現實生活中,如果要保證該書不會被多個售貨員同時賣掉,必須要有一種機制來保證:
          比如,售貨員應該拿到該書之后才能開始賣書,暫時拿不到的話就只能等該書被退回柜臺。

          售書的完整的例子可以參考 范例解說Java里的線程概念與線程同步技術 一文

          這里,每一個售貨員售書可以看作一個線程。欲售的書便是各線程需要共享的資源。
          開始售書之前,需要取得該書(資源),取不到情況下等待:資源取得
          開始售書之后,則需要取得對該書的獨享控制(不讓他人拿到該書):資源加鎖
          售完書時,需要通知柜臺該書已售出;或者未售出時,把書退回柜臺(通知他人可以拿到該書):資源解鎖

          synchronized控制線程同步的概念跟此完全一樣。
          Java里可以使用synchronized來同步代碼塊或者方法。
          同步代碼塊例:
          1. synchronized(欲同步的對象obj) {
          2.     需要同步的代碼塊   
          3. }  

          可以同步代碼塊。

          synchronized (obj) 表示若多個線程同時訪問時,只讓其中一個線程最先取得obj對象并對其加鎖,其它線程則阻塞直到取得obj對象的線程執行完代碼塊,此時被加鎖的obj對象得到釋放(解鎖),其它線程得到通知取得該book對象繼續執行。
          很多情況下,可以使用synchronized (this){...}來同步代碼塊。但需要注意的是,使用this作為同步對象的話,如果同一個類中存在多個synchronized (this){...}代碼塊,其中任何一個synchronized(this)代碼塊處于被執行狀態,則其它線程對其他synchronized(this)代碼塊的訪問也會受到阻塞。
          為了說明這個問題,我們舉例說明:

          HelloSynchronized.java
          1. publicclass HelloSynchronized {   
          2. publicstaticvoid main(String[] args) {   
          3. //
          4.         HelloSynchronized helloSynchronized = new HelloSynchronized();   
          5. //創建2個線程t1, t2,分別調用HelloSynchronized helloSynchronized的2個方法method1,與method2
          6.         Thread t1 = new Thread(new HelloSynchronizedRunnalbe(helloSynchronized, "method1"), "t1");   
          7.         Thread t2 = new Thread(new HelloSynchronizedRunnalbe(helloSynchronized, "method2"), "t2");   
          8.         t1.start();   
          9.         t2.start();   
          10.     }   
          11. //synchronized public void method1() {    //同步方法
          12. publicvoid method1() {   
          13. synchronized (this) {    //同步塊
          14.             System.out.println(Thread.currentThread().getName()
          15.                     + " enter method1");   
          16. try {
          17.                 Thread.sleep(3000);   
          18.             } catch (InterruptedException e) {
          19. // do nothing
          20.             }   
          21.             System.out.println(Thread.currentThread().getName()
          22.                     + " exit method1");   
          23.         }   
          24.     }   
          25. //synchronized public void method2() {    //同步方法
          26. publicvoid method2() {   
          27. synchronized (this) {    //同步塊
          28.             System.out.println(Thread.currentThread().getName()
          29.                     + " enter method2");   
          30. try {
          31.                 Thread.sleep(3000);   
          32.             } catch (InterruptedException e) {
          33. // do nothing
          34.             }   
          35.             System.out.println(Thread.currentThread().getName()
          36.                     + " exit method2");   
          37.         }   
          38.     }   
          39. }   
          40. class HelloSynchronizedRunnalbe implements Runnable {   
          41. private HelloSynchronized helloSynchronized;
          42. private String methodName;   
          43. public HelloSynchronizedRunnalbe(HelloSynchronized helloSynchronized, String methodName) {
          44. this.helloSynchronized = helloSynchronized;
          45. this.methodName = methodName;   
          46.     }   
          47. publicvoid run() {   
          48. if (methodName.equals("method1")) {   
          49.             helloSynchronized.method1();   
          50.         } elseif (methodName.equals("method2")) {   
          51.             helloSynchronized.method2();   
          52.         }   
          53.     }   
          54. }  


          運行結果為:
          t1 enter method1
          t1 exit method1
          t2 enter method2
          t2 exit method2
          等到線程t1結束后,t2才開始運行(t2受到阻塞)

          再把synchronized (this)去掉,運行結果為:
          t1 enter method1
          t2 enter method2
          t1 exit method1
          t2 exit method2
          線程t1,t2同時運行

          同步方法例:
          1. synchronizedprivatevoid sellBook(Book book) {   
          2. ...   
          3. }  

          這種方法其實相當于
          1. privatevoid sellBook(Book book) {   
          2. synchronized(this) {   
          3.         ...   
          4.     }   
          5. }  

          由于默認采用this作為同步對象,所以當一個類中有多個synchronized方法時,同樣會存在以上問題:即如果有一個線程訪問其中某個synchronized方法時,直到該方法執行完畢,其它線程對其它synchronized方法的訪問也將受到阻塞。
          大家可以把上面的例子稍加改造,去掉代碼中的synchronized (this),改為synchronized public void method1(),synchronized public void method2()同步形式,運行后會得到同樣結果。

          多同步代碼塊synchronized(this){...}的多線程阻塞問題(包括synchronized同步方法),在并發處理的系統中(比如WEB服務器)會嚴重影響性能,建議慎重使用。可以使用synchronized(obj){...}縮小同步資源對象的范圍來解決這個問題。

          posted @ 2009-12-14 19:33 異域流浪 閱讀(288) | 評論 (0)編輯 收藏

          【轉】范例解說Java里的線程概念與線程同步技術

          線程 是一段完成某個特定功能的代碼,程序中的執行線程。Java 虛擬機允許應用程序并發地運行多個執行線程。
          每個線程都有一個優先級,高優先級線程的執行優先于低優先級線程。
          進程不同的是,由同名類生成的多個線程共享相同的內存空間和系統資源。

          線程與進程的區別:
          一個線程是一個程序內部的順序控制流。
          1. 進程:每個進程都有獨立的代碼和數據空間(進程上下文) ,進程切換的開銷大。線程:同一類線程共享代碼和數據空間,每個線程有獨立的運行棧和程序計數器(PC),線程切換的開銷小。
          2. 一個進程中可以包含多個線程。

          本文將介紹以下線程方面的知識:
          1,線程的創建
          2,線程的狀態
          3,線程同步
          4,線程組

          理解線程的最有效的方法是通過實例來理解。下面我們將通過 售貨員售書 為例,由淺入深地介紹線程的創建,通信,鎖機制等概念。

          售貨員售書
          我們假設一下售貨員售書的操作流程:
          1,我們假設有20本書,交給2個售貨員去賣。
          2,售貨員可以賣掉任何一本尚未賣出去的書。換句話說,同一本書若被其中一位售出去了,則不能被另外一位再售出了。


          清單1:
          文件名說明
          Book.java 書籍類
          SellBookRunnable.java 售書類,線程的創建方法之一,該類實現了Runnable 接口,并實現了 run 方法。
          SellBookThread.java 售書類,線程的創建方法之一,該類聲明為 Thread 的子類,并重寫 Thread 類的 run 方法。
          CallSellBook.java 調用類。該類分別介紹了2種不同線程創建的調用方法。

          Book.java
          1. publicclass Book {   
          2. private String name;
          3. privateboolean sold = false;   
          4. public Book(String name) {   
          5. this.name = name;
          6.     }   
          7. public String getName() {
          8. return name;
          9.     }   
          10. publicvoid setName(String name) {   
          11. this.name = name;   
          12.     }   
          13. publicboolean isSold() {   
          14. return sold;
          15.     }   
          16. publicvoid setSold(boolean sold) {   
          17. this.sold = sold;   
          18.     }   
          19. }  



          SellBookRunnable.javatil.List;
          1. publicclass SellBookRunnable implements Runnable {   
          2. private String saleMan;
          3. private List<Book> bookList;
          4. public SellBookRunnable(String saleMan, List<Book> bookList) {
          5. this.saleMan = saleMan;   
          6. this.bookList = bookList;   
          7.     }   
          8. publicvoid run() {   
          9. for (int i = 0; i < bookList.size(); i++) {
          10.             Book book = bookList.get(i);   
          11.             sellBook(book);   
          12.         }   
          13.     }   
          14. /**  
          15.      * 售貨員賣書。我們這樣描述售貨員的賣書過程。  
          16.      *   
          17.      * @param book Book  
          18.      */
          19. privatevoid sellBook(Book book) {   
          20. //從開始售書-到售書完成,使用synchronized (book)保證book不被其他售貨員售出
          21. synchronized (book) {
          22. if (book.isSold()) {   
          23. return;
          24.             } else {
          25. try {
          26. //為了讓各線程有執行機會,設置平均售書時間為0.5秒
          27.                     Thread.sleep(500);   
          28.                 } catch (Exception e) {   
          29.                 }   
          30. //設置已售標志
          31.                 book.setSold(true);   
          32. //打印該書已售信息
          33.                 System.out.println("[" + saleMan + "]" + book.getName() + " sold out:"
          34.                         + book.isSold() + ". by "
          35.                         + Thread.currentThread().getName());
          36.             }   
          37.         }   
          38.     }   
          39. }  



          SellBookThread.java

          1. import java.util.List;
          2. publicclass SellBookThread extends Thread {   
          3. private String saleMan;
          4. private List<Book> bookList;
          5. public SellBookThread(String saleMan, List<Book> bookList) {
          6. this.saleMan = saleMan;   
          7. this.bookList = bookList;   
          8.     }   
          9. publicvoid run() {   
          10. for (int i = 0; i < bookList.size(); i++) {
          11.             Book book = bookList.get(i);   
          12.             sellBook(book);   
          13.         }   
          14.     }   
          15. /**  
          16.      * 售貨員賣書。我們這樣描述售貨員的賣書過程。  
          17.      *   
          18.      * @param book Book  
          19.      */
          20. privatevoid sellBook(Book book) {   
          21. //從開始售書-到售書完成,使用synchronized (book)保證book不被其他售貨員售出
          22. synchronized (book) {
          23. if (book.isSold()) {   
          24. return;
          25.             } else {
          26. try {
          27. //為了讓各線程有執行機會,設置平均售書時間為0.5秒
          28.                     Thread.sleep(500);   
          29.                 } catch (Exception e) {   
          30.                 }   
          31. //設置已售標志
          32.                 book.setSold(true);   
          33. //打印該書已售信息
          34.                 System.out.println("[" + saleMan + "]" + book.getName() + " sold out:"
          35.                         + book.isSold() + ". by "
          36.                         + Thread.currentThread().getName());
          37.             }   
          38.         }   
          39.     }   
          40. }  



          CallSellBook.java

          1. import java.util.ArrayList;
          2. import java.util.List;
          3. //該類調用SellBookXxx類
          4. publicclass CallSellBook {   
          5. /**  
          6.      * 用線程模擬這個售書的過程  
          7.      */
          8. publicstaticvoid main(String[] args) {   
          9. //方法1:
          10.         callSellBookThread();   
          11. //or
          12. //方法2:
          13. //callSellBookRunnable();
          14.     }   
          15. //調用SellBookRunnable(Runnable接口實現類)模擬售書過程
          16. publicstaticvoid callSellBookThread() {   
          17.         List <Book>bookList = getBookListForSale();
          18. //將預售書籍清單交給售貨員SaleMan1
          19.         Thread t1 = new SellBookThread("SaleMan1", bookList);   
          20. //將預售書籍清單交給售貨員SaleMan2
          21.         Thread t2 = new SellBookThread("SaleMan2", bookList);   
          22. //售貨員SaleMan1開始售書
          23.         t1.start();   
          24. //售貨員SaleMan2開始售書
          25.         t2.start();   
          26.     }   
          27. //調用SellBookRunnable(Runnable接口實現類)模擬售書過程
          28. publicstaticvoid callSellBookRunnable() {   
          29.         List <Book>bookList = getBookListForSale();
          30. //將預售書籍清單交給售貨員SaleMan1
          31.         Thread t1 = new Thread(new SellBookRunnable("SaleMan1", bookList));   
          32. //將預售書籍清單交給售貨員SaleMan2
          33.         Thread t2 = new Thread(new SellBookRunnable("SaleMan2", bookList));   
          34. //售貨員SaleMan1開始售書
          35.         t1.start();   
          36. //售貨員SaleMan2開始售書
          37.         t2.start();   
          38.     }   
          39. //準備預售書籍
          40. publicstatic List<Book> getBookListForSale() {
          41.         List <Book>bookList = new ArrayList();   
          42. for (int i = 0; i < 20; i++) {   
          43.             Book book = new Book("Book" + i);   
          44.             bookList.add(book);   
          45.         }   
          46. return bookList;   
          47.     }   
          48. }  


          執行CallSellBook
          [SaleMan1]Book0 sold out:true. by Thread-0
          [SaleMan2]Book1 sold out:true. by Thread-1
          [SaleMan2]Book2 sold out:true. by Thread-1
          [SaleMan2]Book3 sold out:true. by Thread-1
          [SaleMan2]Book4 sold out:true. by Thread-1
          [SaleMan2]Book5 sold out:true. by Thread-1
          [SaleMan1]Book6 sold out:true. by Thread-0
          [SaleMan1]Book7 sold out:true. by Thread-0
          [SaleMan1]Book8 sold out:true. by Thread-0
          [SaleMan1]Book9 sold out:true. by Thread-0
          [SaleMan1]Book10 sold out:true. by Thread-0
          [SaleMan1]Book11 sold out:true. by Thread-0
          [SaleMan2]Book12 sold out:true. by Thread-1
          [SaleMan2]Book13 sold out:true. by Thread-1
          [SaleMan2]Book14 sold out:true. by Thread-1
          [SaleMan2]Book15 sold out:true. by Thread-1
          [SaleMan2]Book16 sold out:true. by Thread-1
          [SaleMan2]Book17 sold out:true. by Thread-1
          [SaleMan1]Book18 sold out:true. by Thread-0
          [SaleMan1]Book19 sold out:true. by Thread-0
          線程的創建
          創建新執行線程有兩種方法。
          方法一種方法是將類聲明為 Thread 的子類。該子類應重寫 Thread 類的 run 方法。事實上類Thread本身也實現了接口Runnable,所以我們可以同過繼承Thread類實現線程體。
          參考:SellBookThread.javaCallSellBook.java
          另一種方法是聲明實現 Runnable 接口的類。該類然后實現 run 方法。
          參考:SellBookRunnable.javaCallSellBook.java



          線程的狀態
          線程有四種狀態:創建狀態(New),可運行狀態(Runnable),阻塞狀態(Blocked),死亡狀態(Dead)。

          創建狀態(New):
          當執行完
          Thread t1 = new SellBookThread("SaleMan1", bookList);
          語句之后,則t1處于創建狀態(New)。此時t1并未真正運行。

          可運行狀態(Runnable):
          當Thread t1被創建,并執行完
          t1.start();
          語句之后,t1就處于可運行狀態(Runnable)。此時,系統為線程t1分配其所需的系統資源。并對t1加以調用(或者根據任務調度情況準備調用)。

          阻塞狀態(Blocked):
          由于以下原因:
          1) 調用了sleep()方法;
          2) 調用了suspend()方法(該方法已不推薦使用);
          3) 為等待條件鎖,調用wait()方法等;
          4) 輸入輸出,或消息發生阻塞;

          使得線程處于阻塞狀態(Blocked)。處于該狀態的線程即使處理器空閑,也不會得到執行。

          死亡狀態(Dead):
          死亡狀態(Dead)可以為自然死亡(線程運行完畢),或者調用了stop()方法(該方法已不推薦使用)。


          線程的優先級:
          可以通過Thread類的    
          void setPriority(int newPriority)
          方法為線程設置優先級。但是不能保證高優先級的線程就會被先運行。

          線程組:
          可以通過
          ThreadGroup group = new ThreadGroup(groupName);
          Thread t1 = new Thread(ThreadGroup g, Runnable r1);
          Thread t1 = new Thread(ThreadGroup g, Runnable r2);
          等方法把多個線程加到一個線程組里去,這樣可以通過ThreadGroup對這些線程進行某些統一操作,
          例如:group.interrupt();中斷該組所有線程。


          線程unchecked異常處理器:
          可以通過:
          public void static Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler)
          方法為所有線程指定一個unchecked異常處理器,該處理器必須實現UncaughtExceptionHandler接口。


          線程同步:
          線程同步指多個線程同時訪問某資源時,采用一系列的機制以保證同時最多只能一個線程訪問該資源。
          線程同步是多線程中必須考慮和解決的問題,因為很可能發生多個線程同時訪問(主要是寫操作)同一資源,如果不進行線程同步,很可能會引起數據混亂,造成線程死鎖等問題。

          使用synchronized同步線程。
          在J2SE5.0之前,只能使用synchronized來同步線程。可以使用synchronized來同步代碼塊或者方法。
          同步代碼塊例:
          synchronized(欲同步的對象obj) {需要同步的代碼塊}可以同步代碼塊。

          參考:SellBookThread.java
          1. privatevoid sellBook(Book book) {   
          2. synchronized (book) {
          3.             ...   
          4.         }   
          5.     }  

          該例synchronized (book) 表示若多個線程同時訪問時,只讓其中一個線程最先取得book對象,其它線程則阻塞直到代碼塊執行完畢book對象被釋放后,其它線程才能取得該book對象繼續執行。
          很多情況下,可以使用synchronized (this){...}來同步代碼塊。但需要注意的是,使用this作為同步對象的話,如果同一個類中存在多個synchronized (this){...}代碼塊,其中任何一個synchronized(this)代碼塊處于被執行狀態,則其它線程對其他synchronized(this)代碼塊的訪問也會受到阻塞。

          同步方法例:
          1. synchronizedprivatevoid sellBook(Book book) {   
          2. ...   
          3. }  

          這種方法其實相當于
          1. privatevoid sellBook(Book book) {   
          2. synchronized(this) {   
          3.         ...   
          4.     }   
          5. }  

          由于默認采用this作為同步對象,所以當一個類中有多個synchronized方法時,同樣會存在以上問題:即如果有一個線程訪問其中某個synchronized方法時,直到該方法執行完畢,其它線程對其它synchronized方法的訪問也將受到阻塞。
          有關synchronized詳細說明我們將在其它文章中加以說明。


          使用java.util.concurrent.locks.ReentrantLock和java.util.concurrent.locks.ReentrantReadWriteLock類同步線程。
          J2SE5.0加入了ReentrantLock和ReentrantReadWriteLock可以對線程進行同步,這里舉一個最簡單的例子對其加以說明:
          1. class X {
          2. privatefinal ReentrantLock lock = new ReentrantLock();   
          3. // ...
          4. publicvoid m() {    
          5.      lock.lock();  // block until condition holds
          6. try {
          7. // ... method body
          8.      } finally {
          9.        lock.unlock()   
          10.      }   
          11.    }   
          12.  }   



          其它J2SE5.0新導入的有關線程的相關接口/類:
          java.util.concurrent.Future
          Future接口可以保持/取得異步執行的結果值

          java.util.concurrent.Callable
          類似于Runnable接口。但Runnable不能返回值,也不能拋出checked異常

          java.util.concurrent.ExecutorService
          該接口繼承了Executor接口。可以通過submit方法把Runnable,Callable對象轉換為Future 形式。

          java.util.concurrent.FutureTask
          該類實現了Runnable和Future接口。提供異步執行的取消以及異步執行結果的取得等功能。

          java.util.concurrent.Executor
          執行指定的Runnable對象

          java.util.concurrent.Executors
          工具類。提供靜態方法可以創建Executor,ExecutorService,Callable等對象。可以通過newCachedThreadPool()等方法簡單創建線程池。


          posted @ 2009-12-14 19:29 異域流浪 閱讀(253) | 評論 (0)編輯 收藏

          【轉】JAVA 基本數據類型 取值范圍

          先看一段代碼
          public class Hello{
              public static void main(String[] args){
                  int i  = 5 ,  j = 2;
                  System.out.println(i+j);
                  System.out.println(i-j);
                  System.out.println(i*j);
                  System.out.println(i/j);
              }
          }

          編譯運行完上面的代碼后會得到各條指令運行的結果:7,3,10,2
          這就是JAVA里面的加減乘除運算,為什么5除以2不等于2.5而等于2呢?這是因為這里做的是整數的四則運算,5除以2的結果是2,而余數為1,我們可以在上面的代碼上加上一條指令
          System.out.println(i%j);
          運行這個結果就會得到余數 1,這個 “%”執行的求余,或者叫取模。
          想要得到5/2=2.5這個結果,我們需要改變對i和j的定義
          把 int i = 5 ,  j=2;  改寫成double i =5 , j = 2;
          再編譯運行一次,會得到如下的結果: 7.0 , 3.0 , 10.0 , 2.5.
          可以看到結果都發生了變化,變成了帶小數點的,我們稱之為浮點型常量。
          跟前面的例子一樣,我們也使用了這樣的定義方法
          int i = 5,j = 2;
          Scanner s = new Scanner(System.in);
          前面說過,我們在這里是定義了一個Scanner類型的引用變量,它指向一個Scanner對象,但是這里跟以前有點不一樣(大概是java中僅有的幾處不一樣的地方了),我們定義了一個int型的變量i,然后把它的值賦成5(不是指向5),以后用到它的地方就相當于在用5做計算。
          int是我們常用到八種基本數據類型之一,它表示整數型。
          在JAVA中一共有八種基本數據類型,他們分別是
          byte、short、int、long、float、double、char、boolean
          整型
          其中byte、short、int、long都是表示整數的,只不過他們的取值范圍不一樣
          byte的取值范圍為-128~127,占用1個字節(-2的7次方到2的7次方-1)
          short的取值范圍為-32768~32767,占用2個字節(-2的15次方到2的15次方-1)
          int的取值范圍為(-2147483648~2147483647),占用4個字節(-2的31次方到2的31次方-1)
          long的取值范圍為(-9223372036854774808~9223372036854774807),占用8個字節(-2的63次方到2的63次方-1)
          可以看到byte和short的取值范圍比較小,而long的取值范圍太大,占用的空間多,基本上int可以滿足我們的日常的計算了,而且int也是使用的最多的整型類型了。
          在通常情況下,如果JAVA中出現了一個整數數字比如35,那么這個數字就是int型的,如果我們希望它是byte型的,可以在數據后加上大寫的B:35B,表示它是byte型的,同樣的35S表示short型,35L表示long型的,表示int我們可以什么都不用加,但是如果要表示long型的,就一定要在數據后面加“L”。

          浮點型
          float和double是表示浮點型的數據類型,他們之間的區別在于他們的精確度不同
          float 3.402823e+38 ~ 1.401298e-45(e+38表示是乘以10的38次方,同樣,e-45表示乘以10的負45次方)占用4個字節
          double 1.797693e+308~ 4.9000000e-324 占用8個字節
          double型比float型存儲范圍更大,精度更高,所以通常的浮點型的數據在不聲明的情況下都是double型的,如果要表示一個數據是float型的,可以在數據后面加上“F”。
          浮點型的數據是不能完全精確的,所以有的時候在計算的時候可能會在小數點最后幾位出現浮動,這是正常的。

          boolean型(布爾型)
          這個類型只有兩個值,true和false(真和非真)
          boolean t = true;
          boolean f = false;
          char型(文本型)
          用于存放字符的數據類型,占用2個字節,采用unicode編碼,它的前128字節編碼與ASCII兼容
          字符的存儲范圍在\u0000~\uFFFF,在定義字符型的數據時候要注意加' ',比如 '1'表示字符'1'而不是數值1,
          char c = ' 1 ';
          我們試著輸出c看看,System.out.println(c);結果就是1,而如果我們這樣輸出呢System.out.println(c+0);
          結果卻變成了49。
          如果我們這樣定義c看看
          char c = ' \u0031 ';輸出的結果仍然是1,這是因為字符'1'對應著unicode編碼就是\u0031
          char c1 = 'h',c2 = 'e',c3='l',c4='l',c5 = 'o';
          System.out.print(c1);System.out.print(c2);System.out.print(c3);System.out.print(c4);Sytem.out.print(c5);

          String
          在前面我們看到過這樣的定義:
          String s = "hello";
          System.out.println(s);跟上面的5條語句組合起來的效果是一樣的,那么String是個什么呢?String是字符串,它不是基本數據類型,它是一個類,但是它又是一個有一點點特殊的類,它有很多性質和基本數據類型很像,以后我們會慢慢看到這些。

          posted @ 2009-12-01 18:03 異域流浪 閱讀(234) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 迭部县| 乳源| 西青区| 于田县| 威远县| 澳门| 申扎县| 博罗县| 格尔木市| 祁连县| 清新县| 饶河县| 泌阳县| 明星| 葫芦岛市| 长沙市| 延津县| 资源县| 武宣县| 楚雄市| 阳西县| 桂东县| 嘉善县| 嵊州市| 宁河县| 阿坝县| 德清县| 体育| 鄂州市| 乌兰察布市| 南川市| 泰顺县| 阿合奇县| 长顺县| 涿鹿县| 辽宁省| 桐梓县| 牙克石市| 陕西省| 嘉峪关市| 靖安县|