蘋果的成長日記

          我還是個青蘋果呀!

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            57 隨筆 :: 0 文章 :: 74 評論 :: 0 Trackbacks

          我的評論

          我這段時間也在跟老公辦理隨遷,也真是給氣得不行。

          前樓主是寫得是很詳細,但我想再問一下計劃生育證明,去派出所交資料就說差計劃生育證明,但我去深圳的我戶口的街道辦去辦理,又要說要老公老家當地戶口所在地的計劃生育證明,深圳這邊的才能開。還需要我戶口本的首頁。要不我這邊的街道辦不給開計劃生育證明。

          所以請各位知道的能盡快幫忙告訴。非常的感謝。
          re: JXL操作Excel[未登錄] 蘋果 2008-05-29 11:49  
          簡練!精煉!易懂! 好東西,值得學習!
          如何制作銀行支出表
          謝謝,已收到,希望相互多多交流
          謝謝,也給我發一份吧!
          steven.yj@163.com
          每個包使用一個特性文件,按類名稱來限定鍵。
          re: 【轉載】java collection framwork 蘋果 2005-06-28 15:41  
          Map:關心唯一標識符。把唯一鍵(ID)映射為具體值,當然,鍵和值二者都是對象。這里,位于Map中的鍵基于鍵的散列碼,因此,hashCode()設計越有效,訪問性能越好。
          HashMap:未分類未排序
          適合:需要Map,而不關心其順序(當遍歷它時),則HashMap是一種方法,其他映射增加更多的開銷。HashMap允許在一個集合中有一個null鍵和在一個集合中有多個null值。
          Hashtable:是HashMap的同步版本。
          記住:不要同步類,所謂同步,是指同步該類的主要方法。HashMap允許有null值和一個null鍵,但是Hashtable不允許有任何內容為null。
          LinkedHashMap:維護插入順序(或者訪問順序)。添加和刪除元素比HashMap慢,但是遍歷得更快。
          TreeMap:分類排序。
          re: 【轉載】java collection framwork 蘋果 2005-06-28 15:24  
          所謂的有序就是你能夠按照某種特定的(而不是隨機的)順序遍歷這個集合。所謂的分類是指按照自然順序分類的集合。排序的集合如果使用自然順序或者在分類集合的構造函數中定義排序規則,就認為是分類的。 Set:關心唯一性——它不允許重復。equals()方法確定兩個對象是否完全相同。
          HashSet: 未排序未分類,它使用被插入對象的散列碼。因此,hashCode()設計越有效,訪問性能越好。
          適合:需要集合不具有任何重復值,并且遍歷它不關心順序時。
          LinkedHashSet:LinkedHashSet是HashSet的排序版本。可以構造一個按元素的訪問順序排序而不是插入順序排序的LinkedHashSet。
          適合:當關心遍歷順序時。如果想建立最近最少使用緩存
          TreeSet: 排序、分類。使用一種Red-Black樹結構,并保證元素將按照元素的自然順序(可以在構造函數里提供規則)進行升序排列。
          re: 【轉載】java collection framwork 蘋果 2005-06-28 15:15  
          List: List只關心索引。所有三種List設計都是按照索引位置排序
          ArrayLsit:
          可以看做一個可增長的數組,特點是快速遍歷和快速隨機訪問。排序但沒有分類。
          適合場所:需要快速遍歷但不可能做大量的插入和刪除
          Vector:
          基本與ArrayList相同,但是,為了安全起見,Vector()方法被同步了。通常會使用ArrayList而不是Vector,以免不必要的性能損失。如果確實需要線程安全,在Collections類中有些實用方法能夠解決。
          LinkedList:按照索引位置排序,它象ArrayList一樣,除了元素相互之間是雙鏈接之外。這種鏈接為從頭到尾添加和刪除提供新的方法(除了List接口得到的之外),適合用于設計棧和隊列。
          LinkedList遍歷可能比ArrayList慢,適合:需要快速插入和刪除。
          re: 【Java面試題集錦系列一】 蘋果 2005-06-24 15:11  
          垃圾收集器
          java的垃圾收集器為內存管理提供了一種自動解決方案。在多數情況下,它把你從必須為應用程序添加所有內存管理中解脫出來。自動垃圾收集的缺點是不能完全控制它什么時候執行以及什么時候不執行。
          堆是java對象所在的內存部分,它是垃圾收集處理所涉及的一塊也是唯一的一塊內存。所有的垃圾收集考慮的是要確保堆有盡可能多的自由空間。問題的核心就是要刪除運行的java程序不能再到達的任何對象。當垃圾收集器運行時,其目的時查找和刪除不能被訪問的對象,如果把java程序看作是處于一個這樣的固定循環中:創建它所需的對象(這要占用堆上的空間),之后當不再需要他們時廢棄它們,創建新的對象,再廢棄它們,如此循環,這個問題中缺少的一部分是垃圾收集器。當它運行時,它從內存中查找那些被廢棄的對象,并刪除它們,這樣使使用內存和釋放內存的循環能夠繼續。
          1。垃圾收集器什么時候運行?
          垃圾收集器受JVM控制,JVM決定什么時候運行垃圾收集器。從Java程序內可以請求JVM運行垃圾收集器,但是,在任何情況下都無法保障JVM會答應你的請求。JVM通常會在它感到內存減少時運行垃圾收集器。經驗告訴我們:當java程序請求進行垃圾收集時,JVM通常會在短期內響應請求,但這沒有任何保障。剛好在你認為可以依靠它時,JVM可能會忽略你的請求。
          2.GC怎樣工作?
          什么時候對象變得符合垃圾收集條件?每個java程序有一個或多個線程,每個線程都有其自己的小執行棧。通常,在一個java程序中至少要運行一個線程,即棧底部main()方法的線程。出了有其自己的小執行棧外,每個線程都有其自己的生命周期。線程可以是死的或活的,當沒有任何活線程能夠訪問一個對象時,該對象就符合垃圾收集條件。
          根據這一定義,GC做一些不可思議的未知操作,當它發現一個對象不能被任何活線程訪問時,它將認為該對象符合刪除條件,它可能在某時刪除它(它也可能不刪除它)。所謂到達一個對象,實際上是有一個可到達的引用變量引用所討論的對象。如果我們的java程序有一個引用變量引用一個對象,并且該引用變量可用于一個活線程,則該對象被認為是可到達的。
          注意:一個java程序能夠耗盡內存。垃圾收集系統嘗試在對象不被使用時把它們從內存中刪除。然而,如果保持太多活對象(被其他活對象引用的對象),系統則會耗盡內存。垃圾收集不能保證有足夠的內存,它只能保證可以使用的內存將盡可能被有效地管理。
          3.編寫代碼明確使對象符合搜集條件
          怎樣使對象符合垃圾收集條件,怎樣在必要時強制執行垃圾收集,怎樣執行額外地清理?
          1)空引用 把引用該對象的引用變量設置為null,使沒有對它的可到達引用
          public class GarbageTruck {
          public static void main(String[] args) {
          StringBuffer sb = new StringBuffer("hello");
          System.out.println(sb);
          //The StringBuffer object is not eligible for collection
          sb = null;
          //Now the StringBuffer object is eligible for collection
          }
          }
          2)重新為引用變量賦值
          可以通過設置引用變量引用另一個對象來解除該引用變量與一個對象間的引用關系。
          class GarbageTruck {
          public static void main(String [] args) {
          StringBuffer s1= new StringBuffer("hello");
          StringBuffer s2= new StringBuffer(goodbye");
          System.out.println(s1);
          //At this point the StringBuffer "hello" is not eligible
          s1=s2;//Redirects s1 to refer to the "goodbye" object
          //Now the StringBuffer "hello" is eligible for collection
          在方法內創建對象也要考慮一下。當調用方法時,所創建的任何局部變量只在該方法期間存在。一旦該方法返回,在這個方法那創建的對象就符合垃圾收集條件。然而,有一種明顯的例外情況,如果一個對象從一個方法被返回,其引用可能在調用它的方法內被賦予一個引用變量,因此它不符合搜集條件。請看下面代碼:
          import java.util.Date;
          public class GarbageFactory {
          public static void main(String[] args) {
          Date d = getDate();
          doComplicatedStuff();
          System.out.println("d = "+d);
          }
          public static getDate() {
          Date d2 = new Date();
          String now = d2.toString();
          System.out.println(now);
          return d2;
          }
          }
          在方法getDate()中,創建了兩個對象,一個Date對象和一個包含日期信息的String對象。因為該方法返回Date對象,所以它將不符合搜集條件,即使在該方法完成之后。然而String對象將符合條件,即使沒有明確把now變量設置為null。
          3.隔離引用
          一般來說,我們把正在計算機中執行的程序叫做"進程"(Process) ,而不將其
          稱為程序(Program)。所謂"線程"(Thread),是"進程"中某個單一順序的控制流。
          新興的操作系統,如Mac,Windows NT,Windows 95等,大多采用多線程的概念,把線
          程視為基本執行單位。線程也是Java中的相當重要的組成部分之一。

            甚至最簡單的Applet也是由多個線程來完成的。在Java中,任何一個Applet的
          paint()和update()方法都是由AWT(Abstract Window Toolkit)繪圖與事件處理線
          程調用的,而Applet 主要的里程碑方法——init(),start(),stop()和destory()
          ——是由執行該Applet的應用調用的。

            單線程的概念沒有什么新的地方,真正有趣的是在一個程序中同時使用多個線
          程來完成不同的任務。某些地方用輕量進程(Lightweig ht Process)來代替線程
          ,線程與真正進程的相似性在于它們都是單一順序控制流。然而線程被認為輕量是
          由于它運行于整個程序的上下文內,能使用整個程序共有的資源和程序環境。

            作為單一順序控制流,在運行的程序內線程必須擁有一些資源作為必要的開銷
          。例如,必須有執行堆棧和程序計數器。在線程內執行的代碼只在它的上下文中起
          作用,因此某些地方用"執行上下文"來代替"線程"。

            2.線程屬性

            為了正確有效地使用線程,必須理解線程的各個方面并了解Java 實時系統。
          必須知道如何提供線程體、線程的生命周期、實時系統如 何調度線程、線程組、
          什么是幽靈線程(Demo nThread)。

            (1)線程體
            所有的操作都發生在線程體中,在Java中線程體是從Thread類繼承的run()方
          法,或實現Runnable接口的類中的run()方法。當線程產生并初始化后,實時系統調
          用它的run()方法。run()方法內的代碼實現所產生線程的行為,它是線程的主要部
          分。

            (2)線程狀態
            附圖表示了線程在它的生命周期內的任何時刻所能處的狀態以及引起狀態改
          變的方法。這圖并不是完整的有限狀態圖,但基本概括了線程中比較感興趣和普遍
          的方面。以下討論有關線程生命周期以此為據。


            ●新線程態(New Thread)
            產生一個Thread對象就生成一個新線程。當線程處于"新線程"狀態時,僅僅是
          一個空線程對象,它還沒有分配到系統資源。因此只能啟動或終止它。任何其他操
          作都會引發異常。
            ●可運行態(Runnable)
            start()方法產生運行線程所必須的資源,調度線程執行,并且調用線程的run
          ()方法。在這時線程處于可運行態。該狀態不稱為運行態是因為這時的線程并不
          總是一直占用處理機。特別是對于只有一個處理機的PC而言,任何時刻只能有一個
          處于可運行態的線程占用處理 機。Java通過調度來實現多線程對處理機的共享。

            ●非運行態(Not Runnable)
            當以下事件發生時,線程進入非運行態。
            ①suspend()方法被調用;
            ②sleep()方法被調用;
            ③線程使用wait()來等待條件變量;
            ④線程處于I/O等待。
            ●死亡態(Dead)
            當run()方法返回,或別的線程調用stop()方法,線程進入死亡態 。通常Appl
          et使用它的stop()方法來終止它產生的所有線程。

            (3)線程優先級
            雖然我們說線程是并發運行的。然而事實常常并非如此。正如前面談到的,當
          系統中只有一個CPU時,以某種順序在單CPU情況下執行多線程被稱為調度(schedu
          ling)。Java采用的是一種簡單、固定的調度法,即固定優先級調度。這種算法是
          根據處于可運行態線程的相對優先級來實行調度。當線程產生時,它繼承原線程的
          優先級。在需要時可對優先級進行修改。在任何時刻,如果有多條線程等待運行,
          系統選擇優先級最高的可運行線程運行。只有當它停止、自動放棄、或由于某種
          原因成為非運行態低優先級的線程才能運行。如果兩個線程具有相同的優先級,它
          們將被交替地運行。
            Java實時系統的線程調度算法還是強制性的,在任何時刻,如果一個比其他線
          程優先級都高的線程的狀態變為可運行態,實時系統將選擇該線程來運行。

            (4)幽靈線程
            任何一個Java線程都能成為幽靈線程。它是作為運行于同一個進程內的對象
          和線程的服務提供者。例如,HotJava瀏覽器有一個稱為" 后臺圖片閱讀器"的幽靈
          線程,它為需要圖片的對象和線程從文件系統或網絡讀入圖片。
            幽靈線程是應用中典型的獨立線程。它為同一應用中的其他對象和線程提供
          服務。幽靈線程的run()方法一般都是無限循環,等待服務請求。

            (5)線程組
            每個Java線程都是某個線程組的成員。線程組提供一種機制,使得多個線程集
          于一個對象內,能對它們實行整體操作。譬如,你能用一個方法調用來啟動或掛起
          組內的所有線程。Java線程組由ThreadGroup類實現。
            當線程產生時,可以指定線程組或由實時系統將其放入某個缺省的線程組內。
          線程只能屬于一個線程組,并且當線程產生后不能改變它所屬的線程組。

            3.多線程程序

            對于多線程的好處這就不多說了。但是,它同樣也帶來了某些新的麻煩。只要
          在設計程序時特別小心留意,克服這些麻煩并不算太困難。

            (1)同步線程
            許多線程在執行中必須考慮與其他線程之間共享數據或協調執行狀態。這就
          需要同步機制。在Java中每個對象都有一把鎖與之對應。但Java不提供單獨的lo
          ck和unlock操作。它由高層的結構隱式實現, 來保證操作的對應。(然而,我們注
          意到Java虛擬機提供單獨的monito renter和monitorexit指令來實現lock和unlo
          ck操作。)
            synchronized語句計算一個對象引用,試圖對該對象完成鎖操作, 并且在完成
          鎖操作前停止處理。當鎖操作完成synchronized語句體得到執行。當語句體執行
          完畢(無論正常或異常),解鎖操作自動完成。作為面向對象的語言,synchronized
          經常與方法連用。一種比較好的辦法是,如果某個變量由一個線程賦值并由別的線
          程引用或賦值,那么所有對該變量的訪問都必須在某個synchromized語句或synch
          ronized方法內。
            現在假設一種情況:線程1與線程2都要訪問某個數據區,并且要求線程1的訪
          問先于線程2, 則這時僅用synchronized是不能解決問題的。這在Unix或Windows
          NT中可用Simaphore來實現。而Java并不提供。在Java中提供的是wait()和noti
          fy()機制。使用如下:
            synchronized method-1(…){ call by thread 1.
            ∥access data area;
            available=true;
            notify()
            }
            synchronized method-2(…){∥call by thread 2.
            while(!available)
            try{
            wait();∥wait for notify().
            }catch (Interrupted Exception e){
            }
            ∥access data area
            }
            其中available是類成員變量,置初值為false。
            如果在method-2中檢查available為假,則調用wait()。wait()的作用是使線
          程2進入非運行態,并且解鎖。在這種情況下,method-1可以被線程1調用。當執行
          notify()后。線程2由非運行態轉變為可運行態。當method-1調用返回后。線程2
          可重新對該對象加鎖,加鎖成功后執行wait()返回后的指令。這種機制也能適用于
          其他更復雜的情況。

            (2)死鎖
            如果程序中有幾個競爭資源的并發線程,那么保證均衡是很重要的。系統均衡
          是指每個線程在執行過程中都能充分訪問有限的資源。系統中沒有餓死和死鎖的
          線程。Java并不提供對死鎖的檢測機制。對大多數的Java程序員來說防止死鎖是
          一種較好的選擇。最簡單的防止死鎖的方法是對競爭的資源引入序號,如果一個線
          程需要幾個資源,那么它必須先得到小序號的資源,再申請大序號的資源。

            4.小結

            線程是Java中的重要內容,多線程是Java的一個特點。雖然Java的同步互斥不
          如某些系統那么豐富,但適當地使用它們也能收到滿意的效果。
          re: 【Java面試題集錦系列一】 蘋果 2005-06-23 21:49  
          Java線程及同步(synchronized)樣例代碼

          --------------------------------------------------------------------------------

          Java線程及同步(synchronized)樣例代碼


          import java.io.*;
          import java.util.*;
          import java.text.SimpleDateFormat;

          public class TestThread extends Thread
          {
          private static Integer threadCounterLock; //用于同步,防止數據被寫亂
          private static int threadCount; //本類的線程計數器

          static
          {
          threadCount = 0;
          threadCounterLock = new Integer(0);
          }

          public TestThread()
          {
          super();
          }

          public synchronized static void incThreadCount()
          {
          threadCount++;
          System.out.println("thread count after enter: " + threadCount);
          }

          public synchronized static void decThreadCount()
          {
          threadCount--;
          System.out.println("thread count after leave: " + threadCount);
          }

          public void run()
          {
          synchronized(threadCounterLock) //同步
          {
          threadCount++;
          System.out.println("thread count after enter: " + threadCount);
          }

          //incThreadCount(); //和上面的語句塊是等價的

          final long nSleepMilliSecs = 1000; //循環中的休眠時間

          long nCurrentTime = System.currentTimeMillis();
          long nEndTime = nCurrentTime + 30000; //運行截止時間
          SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

          try
          {
          while (nCurrentTime < nEndTime)
          {
          nCurrentTime = System.currentTimeMillis();
          System.out.println("Thread " + this.hashCode() + ", current time: " + simpleDateFormat.format(new Date(nCurrentTime)));

          try
          {
          sleep(nSleepMilliSecs);
          }
          catch(InterruptedException ex)
          {
          ex.printStackTrace();
          }
          }
          }
          finally
          {
          synchronized(threadCounterLock) //同步
          {
          threadCount--;
          System.out.println("thread count after leave: " + threadCount);
          }

          //decThreadCount(); //和上面的語句塊是等價的
          }
          }

          public static void main(String[] args)
          {
          TestThread[] testThread = new TestThread[2];
          for (int i=0; i {
          testThread[i] = new TestThread();
          testThread[i].start();
          }
          }
          }

          同步就是簡單的說我用的時候你不能用,大家用的要是一樣的就這樣!
          比如說有只蘋果很好吃,我拉起來咬一口,放下,你再拉起咬一口,這就同步了,要是大家一起咬,呵呵,那就結婚吧,婚禮上常能看到這個,也不怕咬著嘴,嘻嘻嘻!

          舉個例子,現在有個類,類中有一個私有成員一個蘋果,兩個方法一個看,一個吃。
          現在不同步,我一“看”,哈哈一個蘋果,我“吃”四分之一了
          你一“看”,哈哈一個蘋果,也“吃”四分之一了。
          可能的情況就是都是看到一個蘋果但我的吃方法用在你的之前,所以可能你只能吃到3/4的1/4也就是3/16個而不是1/4個蘋果了。
          現在加入同步鎖,我在吃的時候你看被鎖,等吃完了,你再看,啊3/4個蘋果,吃1/3好了了,就這樣!
          re: 【Java面試題集錦系列一】 蘋果 2005-06-23 21:48  
          內部類
          內部類的主要優點之一是內部類實例與外部類實例共享一種“特殊關系”。這種特殊關系為內部類中的代碼提供對封裝(外部)類成員的訪問,就好象內部類是外部類的一部分。不僅是“一部分”,而且是外部類一個羽翼豐滿、帶著卡片的成員。內部類實例可以訪問外部類的所有成員,甚至哪些被標識為private的成員。
          re: 【轉載】java與C++的區別 蘋果 2005-06-23 21:11  
          Java群體每天都在擴大,它既包括一些世界最大的ISV,也包括公司CIO、信息技術人員、系統分析人員、C/S開發人員、編程人員、多媒體設計者、市場行銷人員、教育工作者、經理、影視生產者甚至業余愛好者等廣泛的用戶。從傳統上看,這樣一些人在一起有效地工作是不多見的。當我們談到開放系統時,我們往往是就已發表的API及規格,或者源碼的可得性,或者硬件、聯網及操作系統而言的,沒有一個人是從人的開放意義上來談的。Java完成了開放系統的閉合鏈。它開發了人力資源,而反過來又開辟了共同工作的道路。

          一談到Java,人們馬上會想起一種類似于C++的、適用于分布環境的面向對象編程語言,想到這種語言的簡單、穩定、安全、與體系結構無關、可移植、可解釋、高性能、多線程和動態性等特征。這些都是Java作為一種程序設計語言的主要特征。

          Java是由Sun公司的一個技術小組研制出來的。在實現Java語言的過程中,Sun小組的技術人員很快就意識到:C++無法成為一種完全面向對象的、網絡化的開發語言。C++是通過給原先的C語言增加面向對象功能而開發出來的,因此,它存在著先天不足。這主要體現在C++種類繁多,功能大量冗余,同時又沒有任何一種C++編譯器能夠支持它的全部功能。鑒于這種情況,Sun公司的技術人員決定不擴充C++,而開發一種全新的計算機語言(Java的前身Oak)。但是,C++已經成了大多數編程人員所熟練掌握的語言,Java的設計顯然不能無視這個現實。如果Java和C++之間的差別過大,那么程序員們在學會這種語言的過程中無疑要花費大量的時間和精力。因此,Java保留了盡可能多的C++風格。

          Java自誕生起,為網絡用戶創造了無數客戶端的小應用程序,由于這類應用程序效果良好、數量巨大,以至于許多用戶想到Java編程語言時,會在腦海中出現一個不完全正確的印象-Java是用來編寫小的客戶端程序的。其實,隨著技術的進步,Java語言正在逐步改變自己執行效率較低、無法擔任企業關鍵計算任務的形象,不斷向計算技術的核心地帶前進。今天的Java技術正沿著網絡滲入各個應用領域。

          企業計算:企業計算是Java最重要的技術主題。Sun公司已經公布了企業JavaBean(EJB,Enterprise JavaBean)的規格,隨后眾多公司開始開發企業應用領域的Java技術。IBM公司也已經為Windows NT開發了IBM HPCJ(High Performance Compiler for Java)12.0版,同時研制了IBM JDK(JavaDevelopment Kit)for Windows NT,Novell公司也在宣布了一個新的服務器端的企業Java平臺,而Sun公司也在積極地升級自己的JDK系統,這個形勢表明,Java正在穩步走向企業高端計算。對于Java來說,與其它編程語言爭奪企業計算主力編程工具的優勢在于:其一,Java在進行面向對象的編程工作時,比其它的編程語言如C++更加簡單,因此保證了編程的高效率,減少了編程投入;其二,Java虛擬機技術所提供的"一次編程,到處使用"的跨平臺能力非常適合網絡環境,這給Java在網絡服務器端的發展提供了便利條件;其三,Java擁有強大的提供商和支持者隊伍,該隊伍包括IBM、Oracle、Novell、Sybase和Netscape等公司。

          提速運行:許多企業的應用開發人員非常喜愛Java的語言特性,但是在開發重要系統時,語言特性和執行效率之間的抉擇往往令人傷透腦筋。在關鍵計算中,用戶可能并不在乎數據如何壓縮或者運行的延遲關系如何設置,但是對程序的運行速度卻非常重視,這使廠商將Java的編譯策略開發放在了首位。現在的Java語言,其執行方式已經不僅僅是解釋執行方式了,即時編譯器(JITC、just-in-time compiler)技術和原型編譯技術已經被許多廠家采用,包括Sun、IBM、Oracle以及Netscape等公司在內的技術提供商正在利用這些技術逐步提高Java的執行速度,其中IBM公司早已將Java虛擬機(JVM,JavaVirtual Machine)、操作系統和硬件的特性有機的結合在一起,非常有效地提高了Java的執行效率。

          嵌入計算:嵌入式Java是一個潛力巨大的應用技術,該技術充分發揮了Java小巧靈活的特點。以HP公司為例,該公司以自己的方式制造編譯工具和Java虛擬機,其目的是將Java嵌入各種設備,如打印機、醫學監視器和自動提款機等。嵌入設備依靠一個實時操作系統來處理某一個實時生效的事件,Java被嵌入這些設備后,通過實時擴展(real-time extension)開始發揮作用,使設備具備了一定的智能性,增強了嵌入設備的可管理性和可用性,大大提高了設備的工作效率。各廠商對這一潛力巨大的市場都非常重視,目前該市場缺乏的是一個標準,如果存在標準的話,相信很快就會有大量使用嵌入Java技術的設備上市。

          微軟剛剛發行的Windows XP放棄了對Java的支持,但Java能夠獨立運行于很多操作平臺上,其中也包括Linux,并且在某些特性上要比在Windows上發揮得更好,我們完全有理由拋棄Windows而選擇使用Linux來做Java開發。現在,你可以左手拿著Linux,右手拿著Java,然后對面帶微笑手里拿著Windows XP的Bill Gates說:"讓你的XP去見鬼吧!"

          對于軟件開發者來講,任何一種編程語言都不可能是完美的。如果希望更好地理解Java語言,最好的方法是把這種語言與其同類型的語言相比較。既然Java類似于C++,把它同C++進行一番比較也是順理成章的事情,哪一個好,哪一個不好,每個開發人員都有各自的看法。我個人認為Java開發要比C++好一些。當然每個人的看法和喜好是不同的。后面的文章將向大家介紹Java和C++的不同和對其的改進。孰強孰弱,大家自然就會明白了。

          我們知道,Java一開始采用C++的語法格式,基本上是為了讓程序設計者可以很快地熟悉 Java的語法格式,縮短學習Java的時間,畢竟C和C++仍舊是最多人會的一種程序語言。但是如果我們仔細檢查Java程序語言的許多細節設計,我們可以發現Java去掉了不少C++的特點,并且加入一些新的特性。這些與C++的差異包括:

          1.不再有#define、#include等預處理程序(Preprocessor)的功能

          C++語言很重要的一個特點就是它的預處理程序。有些其他程序語言雖然也加入了#include的功能,但是還是欠缺處理宏(Macro)的能力。#define的功能在Java中我們可以用定義常數(constant)的方式來取代,而#include在Java中是不需要的,因為在Java中程序在執行時,會把類型數據記錄在對象實體之中,我們不需要靠一些標頭文件(header file)來知道我們使用的對象或數值是屬于什么數據類型。

          如果你使用C++語言時,只使用預處理程序的#include和#define功能的話,那么你大概不會覺得Java這樣的設計對你產生什么樣的困擾,但是如果你是使用C++語言預處理程序中宏功能的高手,你可能會覺得很不方便,進而懷疑Java如此設計的意義何在。

          使用預處理程序雖然可以很方便地達到許多功能,但是站在軟件工程的角度上看,對整個軟件的維護其實是很不利的。由于C++語言中預處理程序的功能太過強大,厲害的程序設計高手常會自行開發一套只有自己看的懂的宏語言,一旦整個軟件要交給其他人去維護,后繼者很難在短時間內了解前一個人所寫下的宏功能,增加軟件開發時團隊工作及日后維護的困難度。

          另外一點則是C++語言的編譯器所看到的程序代碼,其實和程序設計者看到的程序代碼是不同的。程序設計者看到的是尚未經過預處理程序處理過的程序代碼,而編譯器看到的則是預處理程序處理過的程序代碼,一旦交給預處理程序處理的宏內容有誤,編譯器產生的錯誤信息將不會是程序設計師所預料的。而這一點自然也增加了程序在排錯時的困難度。

          預處理程序的存在也造成了閱讀程序的不便。如果你想使用別人已經完成的C++語言程序,那么通常你不但要閱讀他所寫下的文件,還必須一并查閱上文件,才能了解其程序的全貌。如果換成是Java程序,只要查看java的程序文件就夠了。

          2.不再有structure、union及typedef

          事實上,早在C++中就可以去掉C語言中的structure和union等對復雜數據的自定結構類型,因為類(Class)的定義方式可以完全做到這項功能。而typedef也是不必要的,一切都用類就可以了。雖然C++這樣的設計是為了和C語言兼容,但是使用多余的語言特點不但不必要,而且容易造成對程序認識的混淆。

          3.不再有函數

          在Java程序語言中,去掉了程序向導語言中最重要的單元--函數(Function)。如果我們以對象向導的觀念來看待函數,就可以了解函數在對象向導的概念中,是不必要的。在對象向導的程序觀念里,對象的數據才是真正的主體,而處理對象數據的方法則必須依附在對象內才有意義。因此,去掉函數并不表示不再有子程序等模組化程 序的概念,相反地,是利用對象中的方法來取代函數,再一次強化對向導的發展策略。

          4.不再有多重繼承(Multiplelnheritance)

          在C++中,多重繼承是一項很強的功能,但也是一般人難以掌控的部分。去掉多重繼承雖然降低了Java語言的功能,但是也大幅簡化撰寫程序時的困難度。雖然移除了多重繼承的功能,但是Java提供了interface的方式,可以達到部分多重繼承的功用。所謂的interface基本上定義了一個類的對外溝通的方法原型,以及類內部的常 數,和多重繼承不同之處在于interface并不會定義類方法的內容,以及類中的變量數據。

          5.不再有Goto

          在程序語言的發展史上,Goto一直是毀譽參半的一項功能。在很多時候使用Goto可以大幅減少不必要的程序代碼,但是也由于Goto可以很自由地改變程序的流程,如果冒然地使用,更可能造成程序結構混亂的情況。一般來說,正確使用Goto的例子多出現在循環內部,想要提早結束某一層循環。在C語言中,我們可以使用break 或contine來改變某一層循環的流程, 但如果想要改變兩層以上的環執行流程,不是使用Goto就是以多余的布爾(boolean)變量,配合上一串if-then-else的判斷來達成。

          Java一方面移除了Goto的功能, 而另一方面同時擴大了break和continue的功能,可以允許多層循環的break或continue。如此一來不但避免了濫用Goto的可能性,同時也保存下Goto的好處。

          6.不再有OperatorOverloading

          在C++中,Operator Overloading同樣也是一項值得討論的設計。幾乎在所有C++的書中,都會引用一些例子,告訴你使用OperatorOverloading可以使你的程序看起來更為自然。如下面是一個程序設計師自定義的復數類:

          //C++中自定義的復數類及0pemtor Overloading
          class Complex{
          public:
          Complex(double real,double image){
          Real_number=real;
          Image_number=image;
          }
          Complex operator+(Complex&rhs){
          Return Complex(rhs.real_number+real_number,
          rhs.image_number+image_,nulnbef);
          }
          private:
          doublereal_number //實部
          doublejmage_nunmber; //虛部
          }



          在這里,如果你使用+來作為復數的加法符號,大家都不會有疑義,但是如果你使用的是*或》這樣的符號,那么別人看到你的程序之后,難保不會產生認識上的錯誤。這也是Operator Overloading一大問題,當大家都對運算符賦予自己的定義后,整個程序的可讀性就會大受影響。Operator Overloading的存在并不是必要的,我們一樣可以定義類中的方法來達到同樣的目的,至于Java去掉這項功能的利弊,恐怕就要讀者自己去評斷了。

          7.取消自動類型轉換

          Java是一個嚴格進行類型檢查的程序語言,對于下面這樣的程序,在C++的編譯器上編譯時最多只會出現警告的信息,但是在Java里則不予通過:

          Int aInteger; Double aDouble=2.71828; AInteger = aDouble;


          雖然這樣的轉型在C++里是合法的,但是也會造成數據精確度的損失。Java為了要確定寫程序的人充分地了解這點,必須要程序設計強制轉型(type casting),Java的編譯器才會接受:

          int aInteger;
          doublea Double=2.71828;
          aInteger=(int)aDouble;



          8.不再有指針

          取消指針(Pointer)這樣數據類型,可能會讓許多熟悉C++語言的程序設計師大吃一驚。在C++語言里,靈活地運用指針是許多程序設計師的得意之作,但是占整個除錯時間最久的也是指針的問題。配合上C++對內存管理的態度,程序設計師必須要自己去追蹤自己向系統要到的內存,最后確實地交還給系統,并且在使用指針時,要小心翼翼地注意不要跨過合法的記憶空間,造成Segmentation Fault或General Protection Fault之類的問題。

          Java去掉了指針類型,并不表示程序設計師在開發高級數據結構,像堆棧(stack)、 隊列(queue)、二元樹(binarytree)時,都必須要像在傳統Basic上,利用大范圍的數組來自行模擬系統內存,自行建構類似指針的表示方式。

          相反地,Java提供了和Lisp語言中相似的Reference類型,通過Reference去讀取配置到的內存內容,可以確保不會去讀取到不屬于自己的內存空間,而另一方面,程序的執行系統也可以動態地去做內存垃圾回收的工作,將沒有被reference參考到的內存空間回收給系統使用。

          9.和C++連接

          不管Java是多么強大,總是有人需要把它和C++連接起來。因為只要有一個新的程序語言或是軟件開發工具一出現,大家就會問:"它是否具有和原有程序庫連接的能力呢?"也因為C++語言在電腦界中占了很重要的地位。大家的問題其實就等于是直接問"它是否可以和C++連接?"。目前在Java中,的確提供了和C++語言連接的方法,它的做法基本上是先將C++語言所寫的程序建構成動態鏈接函數庫(DynamicLinking Library,DLL),再由Java程序去調用DLL里的函數。

          這種連接的方式,使得DLL中的函數,從Java的眼光看就是一個"方法"。不過因為這種方法是直接由其他的程序語言所提供,而不是以Java語言所寫的,所以它被稱之為"原生方法"(NativeMethod)。

          由于Java Applet一些安全上的限制,所以這種連接外部程序的方法只能用在Java Application內。

          小結:

          事實上,constant和typedef這兩條語句包含了#define語句的作用。現在,結構和聯合已經被Java的類所代替。刪除這些特性的原因是:由于其希望維持與C語言的向后兼容性,C ++的語言規范包含了大量冗余。比如,類實際上就已經包括了結構和聯合的作用,因此這兩種數據結構完全可以取消。關于#define語句,Java語言規范的制訂者認為:盡管該語句的出發點是為了增強程序的可讀性,但實際效果卻恰恰相反,它常常導致難讀的代碼,故應該予以取消。Java不再支持獨立函數,因此任何函數都必須封裝到某個類中。由于人們普遍認為, C++所用的超類是非常不穩定的,因此Java拋棄了C++中的多繼承并代之以接口。Java的接口指的是,在別的類看來一個類所能實現的方法。它所顯示的只是一個類的方法或常量和變量 ,而不是這個類的全部結構。

          最后,Java還取消了C++中的GOTO語句、操作符重載、自動類型轉換及指針數據類型。 GOTO語句引起的爭議已經有很多年了,可一直陰魂不散,這跟某些程序員對該語句一直情有獨鐘有關。C++仍然支持數據類型的自動轉換,但Java要求編程人員顯式實現數據類型之間的轉換。自動數據類型轉換使得兩個數據類型互不兼容的變量可以相互賦值,而不需要給出顯式說明。這有時會導致一些問題,其中最常見的是精確度損失。比方說,如果把一個帶符號的32位整數賦給一個無符號整數,則所有的結果均為正數。Java的設計者們認為這很容易引起程序錯誤,從而決定不支持這種轉換方式。
          Java Q&A

          Vector or ArrayList -- which is better?
          Find out the difference between Vector and ArrayList

          By Tony Sintes

          Printer-friendly version | Mail this to a friend


          Vector or ArrayList -- which is better and why?

          Sometimes Vector is better; sometimes ArrayList is better; sometimes you don't want to use either. I hope you weren't looking for an easy answer because the answer depends upon what you are doing. There are four factors to consider:


          API
          Synchronization
          Data growth
          Usage patterns
          Let's explore each in turn.

          API
          In The Java Programming Language (Addison-Wesley, June 2000) Ken Arnold, James Gosling, and David Holmes describe the Vector as an analog to the ArrayList. So, from an API perspective, the two classes are very similar. However, there are still some major differences between the two classes.

          Synchronization
          Vectors are synchronized. Any method that touches the Vector's contents is thread safe. ArrayList, on the other hand, is unsynchronized, making them, therefore, not thread safe. With that difference in mind, using synchronization will incur a performance hit. So if you don't need a thread-safe collection, use the ArrayList. Why pay the price of synchronization unnecessarily?

          Data growth
          Internally, both the ArrayList and Vector hold onto their contents using an Array. You need to keep this fact in mind while using either in your programs. When you insert an element into an ArrayList or a Vector, the object will need to expand its internal array if it runs out of room. A Vector defaults to doubling the size of its array, while the ArrayList increases its array size by 50 percent. Depending on how you use these classes, you could end up taking a large performance hit while adding new elements. It's always best to set the object's initial capacity to the largest capacity that your program will need. By carefully setting the capacity, you can avoid paying the penalty needed to resize the internal array later. If you don't know how much data you'll have, but you do know the rate at which it grows, Vector does possess a slight advantage since you can set the increment value.

          Usage patterns
          Both the ArrayList and Vector are good for retrieving elements from a specific position in the container or for adding and removing elements from the end of the container. All of these operations can be performed in constant time -- O(1). However, adding and removing elements from any other position proves more expensive -- linear to be exact: O(n-i), where n is the number of elements and i is the index of the element added or removed. These operations are more expensive because you have to shift all elements at index i and higher over by one element. So what does this all mean?

          It means that if you want to index elements or add and remove elements at the end of the array, use either a Vector or an ArrayList. If you want to do anything else to the contents, go find yourself another container class. For example, the LinkedList can add or remove an element at any position in constant time -- O(1). However, indexing an element is a bit slower -- O(i) where i is the index of the element. Traversing an ArrayList is also easier since you can simply use an index instead of having to create an iterator. The LinkedList also creates an internal object for each element inserted. So you have to be aware of the extra garbage being created.

          Finally, in "PRAXIS 41" from Practical Java (Addison-Wesley, Feb. 2000) Peter Haggar suggests that you use a plain old array in place of either Vector or ArrayList -- especially for performance-critical code. By using an array you can avoid synchronization, extra method calls, and suboptimal resizing. You just pay the cost of extra development time.

          re: 【Java面試題集錦系列一】 蘋果 2005-06-23 20:52  
          2.HashMap和Hashtable基本相同,只是HashMap是非同步的,并且允許空值。
          ArrayList和Vector的區別也是ArrayList是非同步的(unsyncronized). Hashtable和HashMap的區別: 1.Hashtable是Dictionary的子類,HashMap是Map接口的一個實現類; 2.Hashtable中的方法是同步的,而HashMap中的方法在缺省情況下是非同步的。即是說,在多線程應用程序中,不用專門的操作就安全地可以使用Hashtable了;而對于HashMap,則需要額外的同步機制。但HashMap的同步問題可通過Collections的一個靜態方法得到解決: Map Collections.synchronizedMap(Map m) 這個方法返回一個同步的Map,這個Map封裝了底層的HashMap的所有方法,使得底層的HashMap即使是在多線程的環境中也是安全的。 3.在HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,即可以表示HashMap中沒有該鍵,也可以表示該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵,而應該用containsKey()方法來判斷。 Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會有很大的差異。
          re: 【Java面試題集錦系列一】 蘋果 2005-06-16 13:34  
          下面是我自己的一些注釋:
          1.private 只有本類內的方法才具有訪問權。
          protected 只有本類內的方法、子類以及同一包內的其他類才具有訪問權。
          public 公開訪問
          final 一個常量或者一個不能被重載的類或方法
          finally 一個try塊中總會被執行的部分
          re: Jena推理功能的展示 蘋果 2005-05-26 21:53  
          yujian:
          我按你上面說的運行了一遍,結果是
          list properties of master:
          hastuorof
          沒有錯誤,你可以再運行一遍試試,應該不會有錯,如果還不行,我可以把程序發給你。
          re: Jena推理功能的展示 蘋果 2005-05-20 20:26  
          這個推理程序我用的就是Jena doc中inference小節中的關于計算機的例子,你們沒有嗎?
          我們小組的推理工作剛剛開始,所以自己的推理程序還沒有完成。你們有什么問題,我們可以一起探討一下。
          主站蜘蛛池模板: 清流县| 无锡市| 五华县| 斗六市| 太保市| 贺州市| 阿克陶县| 灵川县| 永昌县| 四子王旗| 汝城县| 贵定县| 易门县| 定西市| 沾益县| 岗巴县| 金川县| 新闻| 六枝特区| 安多县| 桂东县| 广东省| 佛冈县| 太仓市| SHOW| 甘孜| 苍梧县| 互助| 德昌县| 梨树县| 五指山市| 舒城县| 乃东县| 固阳县| 永福县| 红河县| 朔州市| 江阴市| 嫩江县| 新兴县| 荣昌县|