<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我思故我強

    JAVA概念總結(jié)

    傳值與傳引

    嚴格來說,Java中所有方法參數(shù)都是傳值。因為即使是傳遞的參數(shù)是對象的引數(shù)時,引數(shù)本身也是傳值的。所有基本類型都是傳值的。

    傳值:被傳入的參數(shù)被視為內(nèi)部的局域變量,其變化不影響外部變量的原始值。

    傳引對于引數(shù)本身來講也是傳值的,但是在方法內(nèi)部若對引數(shù)所指向的對象屬性有改變,則會直接實時地影響所指向的對象屬性。

    理解傳引這一概念的最佳方式就是畫出指向圖。eg. Aà(Object)O 對于A本身而言它是傳值的,也就是說當(dāng)A作為參數(shù)傳遞的時候,假若在方法內(nèi)部把其它的引數(shù)賦給了A,但是當(dāng)方法返回時,A仍舊是指向原來的對象,而不會改變。其次,對于傳引來說,假若在方法內(nèi)部對A所指向的對象屬性有改變,那么對象屬性的改變會是直接實時的。

    再次強調(diào),Java中所有的參數(shù)傳遞都是傳值的。

    傳值這種題型的考試很多,基本類型傳值問題考的較多的是對某一變量,故意用某一方法試圖改變它,然后方法返回時再打印它。按傳值的說法,實際上該變量并沒有改變。

    構(gòu)造函數(shù)

    a.構(gòu)造器沒有任何返回類型,哪怕是void也不行。假如指定了返回值,那么Java會視為一個普通的方法。

    b.如果沒有顯示地調(diào)用父類的構(gòu)造器,Java總是自動地調(diào)用父類的默認構(gòu)造器。(也就是第一行會默認為super( ))

    c.只要類中顯式地定義一個或多個構(gòu)造器,那么Java不會再為你定義一個默認的構(gòu)造器

    d.構(gòu)造函數(shù)可以被重載,并且在其體內(nèi)可以用this()和super()來調(diào)用其它的構(gòu)造器。但是this()和super()只能放在構(gòu)造函數(shù)體的第一行進行調(diào)用。

    e.構(gòu)造器的修飾符只可以是接入控制符public、private、protected、(default)。其它修飾符一律不可。

    f.構(gòu)造方法不可被繼承。

    重載與覆蓋

      重載的英文為Overload,而覆蓋的英文為Override。重載是出現(xiàn)在同一類中多個同名函數(shù),而覆蓋是出現(xiàn)在類繼承體系中同名函數(shù)。(注意:覆蓋有時被稱為重寫)

      重載是依據(jù)同名方法參數(shù)的個數(shù)、參數(shù)的類型參數(shù)的順序來確定的。方法的修飾符、返回值、拋出的異常均不能作為區(qū)分重載方法的依據(jù)。(繼承體系中也有重載現(xiàn)象)

      覆蓋是在繼承體系中子類覆蓋超類中定義的方法。子類中覆蓋方法的返回類型參數(shù)類型必須精確匹配。接入控制符只能更加公有化;拋出的異常是超類拋出的子集或不拋。

         (static方法不能覆蓋,private方法也不能覆蓋。Java視它們?yōu)楸浑[藏

          · 參數(shù)類型一致,返回類型不同,編譯錯誤,提示“試圖用不兼容的返回類型覆蓋”。

          · 只要參數(shù)類型不一致,返回類型同與不同,編譯都能通過,此不為覆蓋而是重載。

    多態(tài)

      多態(tài)是出現(xiàn)于類的繼承層次中,通過向上轉(zhuǎn)型方法重寫的機制來實現(xiàn)的。

      面向?qū)ο蟪绦蛟O(shè)計的目標是:希望所撰寫的程序代碼都只對基類進行操作。這么一來,當(dāng)加入新的繼承類時,大部分程序代碼都不會受影響而改寫(也即是說代碼具有擴充性)。所以當(dāng)調(diào)用新加入的繼承類時,都會首先向上轉(zhuǎn)型為基類。這就是多態(tài)的向上轉(zhuǎn)型。

      當(dāng)你希望通過調(diào)用基類的方法而能讓繼承類產(chǎn)生正確的行為時,這顯然需要在繼承類進行重寫該方法。而究竟是該調(diào)用哪個繼承類,這是由Java的動態(tài)綁定決定的。

      多態(tài)最重要的一點在于run-time binding。多態(tài)是面向?qū)ο蟪绦蛟O(shè)計的目標。

      關(guān)于多態(tài)中覆蓋注意如下:

    屬性既可以繼承,也是可以“覆蓋”的。但是對屬性而言沒有動態(tài)綁定這一特性,所以覆蓋的屬性被認為是子類的特別屬性。從某種意義上來講,屬性決定了類(性質(zhì))。另一方面,申明的類型就決定了對象的屬性。這是因為,任何對象或變量等號右面是用來賦值給符合等號左面所申明類型的,所以左面的類型是先決條件,賦值必須要符合申明類型。對于向上轉(zhuǎn)型而言,因為等號右面的對象is a申明類型,所以是成立的。一定要記住,屬性永遠都是跟著申明類型走。但是,對方法而言是在運行時動態(tài)綁定的,它取決于對象自身的實際類型(實際上對方法而言,也是先檢查向上轉(zhuǎn)型后的基類該方法,若無該方法的定義,則編譯錯,然后再動態(tài)綁定到繼承類的覆蓋方法)。

    另外,static方法不能覆蓋,private方法也不能覆蓋。

    還需特別注意,方法覆蓋時,若覆蓋得不對(例如參數(shù)一致,僅依靠返回類型不同),則編譯會出錯,而不是被Java認為方法重載(除非參數(shù)類型也不一樣,這樣java會認為不是override,實際上它是overload)。

    類初始化

      類的初始化大致上有這么幾個方面。

    a.靜態(tài)變量的初始化 b.一般實例變量的初始化 c.構(gòu)造函數(shù)的初始化

      初始化的難點在于繼承體系中。當(dāng)有繼承體系時,初始化始終要遵循的原則就是,無論如何必先初始化基類

       0.當(dāng)載入當(dāng)前類時,若當(dāng)前類有繼承體系,則依次無條件載入基類

       0’.先從最頂?shù)幕愰_始順序初始化其靜態(tài)static變量,接著初始化當(dāng)前類的靜態(tài)static變量(也就是說,static變量的初始化是伴隨著類被裝載時而初始化的,它的初始化在任何構(gòu)造函數(shù)執(zhí)行前)

       1.先從最頂端基類,構(gòu)造基類對象。

         (假如構(gòu)造函數(shù)中有this或super調(diào)用,則先執(zhí)行此調(diào)用)

         1.1.首先按出現(xiàn)次序初始化其實例變量

           1.2.再執(zhí)行其構(gòu)造函數(shù)體

       2.依次遞歸上述步驟

      <此外,實例變量可以不顯式初始化(系統(tǒng)會賦默認值),但是局部變量必須顯式初始化>

    異常

    throws是異常的申明,它置于方法的定義處;throw是異常的擲出,它置于方法體內(nèi)。

    異??煞譃榭蓹z測異常和非檢測異常,調(diào)用申明為可檢測異常的方法時必須捕獲異常。

    a.方法申明了可檢測異常,則調(diào)用該方法的塊一定要捕獲異常,否則編譯出錯

       b.throw后面不能跟任何語句,否則編譯提示語句不可到達

         c.多個catch語句,要求更具體的異常在前,超類異常在后,否則編譯出錯

         d.finally語句會在return語句之前執(zhí)行,即在跳出方法之前一定會執(zhí)行finally語句

         e.假如遇到的是System.exit(0),則無論如何,程序馬上退出,finally語句不會執(zhí)行

         f.方法申明了異常,但是在方法體內(nèi)可以不顯示地用throw拋出異常

         g.沒有申明可檢測異常的方法調(diào)用時,不可用catch捕獲,否則編譯出錯

    其它注意:

    a子類中覆蓋的方法只能拋出父類方法拋出異常的子集,也可以不拋出任何異常(這本身就是子集)

       b 但是對于非檢測異常RuntimeException則不會受到上面的約束,它們可以被隨時拋出。也不受范圍限制。

        c 當(dāng)繼承的子類沒有申明異常時,假如它的一個實例被申明為超類(向上轉(zhuǎn)型),這時再調(diào)用子類沒有申明異常的方法,而用了catch,程序也會編譯通過。(實際運行中調(diào)用的還是子類中的方法)

    equals()和==

      對于上述關(guān)于equals()總結(jié)如下:

       a.類型不兼容的兩個對象可以用equals(),但是只要比較的對象類型不同(哪怕值相同),永遠返回false

       b.對于沒有覆蓋equals()的類,即使對象類型相同,值也相同,但返回的仍舊是false,因為它用的是object的默認equals方法(與==相同)

       c然而對于覆蓋equals()的類,只要值相同,便返回true。這些類是String,Wrappers,Date,Calendar,BitSet等

      對于==總結(jié)如下:

       a.類型不兼容的兩個對象不可以用==,若用則編譯錯誤

       b.同種類型的對象,假如不是指引同一個對象,則返回為false(只有指向同一個內(nèi)存塊的對象才返回true)

       c.對于String情況有些不同,因為String對象有字面量和構(gòu)造函數(shù)之分。字面量對象是放在緩沖池中的,這意味著,如果兩個字面量值相同,則第二個對象會指向第一個已經(jīng)存在的對象,而不會新產(chǎn)生,所以==返回的是true。用構(gòu)造器產(chǎn)生的對象同一般對象。對于字面量來說,多個類共享的是同一個緩沖池。這意味著在另外一個類中創(chuàng)建一個先前類中已有的字面量字符串,則仍舊是同一對象。

          另外,注意,toUpperCase()、toLowerCase()方法而言,如果大小寫形式與原始String沒什么差別,方法返回原始對象,==返回true。

       d.對于基本類型而言,系統(tǒng)會自動先歸一精度,然后再比較值,若值相同則返回true。

    String

      String類最重要的一點在于“不變性(immutable)”。它的意思是一旦String類產(chǎn)生了就不會再改變了,若試圖改變它都會產(chǎn)生新的對象。

      String對象有字面量和構(gòu)造函數(shù)之分。字面量對象是放在緩沖池中的,這意味著,如果兩個字面量值相同,則第二個對象會指向第一個已經(jīng)存在的對象,而不會新產(chǎn)生,所以==返回的是true。用構(gòu)造器產(chǎn)生的對象同一般對象。對于字面量來說,多個類共享的是同一個緩沖池。這意味著即使在另外一個類中創(chuàng)建一個先前類中已有的字面量字符串,則仍舊是同一對象。

      考試中需要注意的是:s=new String(“abc”);s+=”def”;System.out.println(s);

                          s=new String(“abc”);s.concat(“def”);System.out.prinln(s);

      前一程序打印為“abcdef”,后一程序打印為“abc”。區(qū)別是第一個程序又重新賦值給了s。而第二個程序中s.concat(“def”)只是產(chǎn)生了一個新的對象但沒有賦給誰,但原來的s不變。

      另外,對于StringBuffer而言是可變的,對它的任何改變都是實時的。

    包裝類

      包裝類是為了方便對基本數(shù)據(jù)類型操縱而出現(xiàn)的。有了包裝類就可以用很多的方法來操縱基本數(shù)據(jù)類型(沒有包裝類想直接對基本數(shù)據(jù)類型操作是不方便的,除非自己編寫方法)。

      要熟悉包裝類應(yīng)該著種理解下面幾點:

      a.包裝類的構(gòu)造器。一般說來,包裝類的構(gòu)造器參數(shù)有兩種:基本數(shù)據(jù)值、字符串

         注意:Boolean包裝類構(gòu)造器當(dāng)傳入字符串時,除了不分大小寫的true返回true外,其它字符串一律返回false

      b.常見的操作方法。例如:轉(zhuǎn)換為本基本類型或其它基本類型的方法

         eg. byteValue(),intValue()…;parseByte(String s),parseInt(String s)…

           c.valueOf(各基本類型或字符串)的使用。ValueOf(str)是包裝類的靜態(tài)方法,作用等同于構(gòu)造器。它會解析傳入的參數(shù),然后構(gòu)造一個相同類型的包裝類,并返回該包裝類。

           例子:原始類型à字符串  (new Integer(101)).toString();String.valueOf(“101”)

                 字符串à(包裝類)à原始類型 Integer.parseInt(“string”);

    (new Integer(“101”)).doubleValue();Integer.valueOf(“101”).intValue()

    Math

      Math類中都是靜態(tài)方法。其中最易錯的是三個方法:ceil(),floor(),round()

    另外還需注意,有許多方法隨基本數(shù)據(jù)類型不同有多個重載版本。eg.abs(),max()

    a.ceil()方法。該方法返回類型為double,往單一的正坐標方向取最近的整數(shù)

    b.floor()方法。該方法返回類型類double,取最靠近其負向的整數(shù)。

    c.round()方法。它有兩個重載版本:double和float,返回分別為long和int

       long round(double a);int round(float)

       round()方法=Math.floor(a+0.5),這意味著正數(shù)5入,負數(shù)6入

       eg.System.out.println(Math.ceil(Double.MIN_VALUE))     //1.0

    System.out.println(Math.floor(-0.1))                //-1.0

    System.out.println(Math.round(-9.5))                //-9

    System.out.println(Math.round(-9.6))                //-10

    System.out.println(Math.round(Double.MIN_VALUE))    //0

    collection

      collection類提供了持有對象的便利性,并對持有對象的操作便利性。正如其名,收集意為將各種類型的對象收在一起,且數(shù)目不限(有點像收集袋)。收集會將放入其中的所有對象均視為Object(向上轉(zhuǎn)型),所以在取出元素對象時,必須顯式(即強制轉(zhuǎn)型)指出其類型。

      對象收集從整體上分為Collection接口和Map接口。這種分類的標準是:某個元素位置上放置元素對象的個數(shù)。顯然,Map接口放置的是一對。

      Collection接口又可擴展為兩個基本接口:List接口和Set接口。

      依上所述,對象收集可以劃分為四個基本的類型:Collection、List、Set、Map

      · Collection 它是一個基類的接口,對元素沒有任何的限制,可以重復(fù)并且無序。

      · List  從其名就知是有序的列表。它描述的是按順序?qū)ο蠓湃肫渲?。顯然,后放入的元素有可能與先前放入的對象是相同的。所以,List是允許對象重復(fù)出現(xiàn)的有序列表。

      · Set   其實就是數(shù)學(xué)上所說的集合,它不允許有重復(fù)的元素。其中可以有空集(即null對象)。Set中的元素不要求有序。

      · Map   即映射,借助于key和value來描述對象的搜索。key域中要求唯一性(其實就是一個Set),value域可以允許有重復(fù)的元素(其實就是一個Collection)。另外注意:常見的HashMap是無序的,而TreeMap是有序的。

    標識符

      a.所有標識符的首字符必須是字母(大小寫)、下劃線_、美元符號$(或符號¥)

    b.接下來的可以是由數(shù)字(0-9)及首字符相同類型的字符(字母、_、$),其它任何特殊字符均不可

    c.標識符不能使用Java關(guān)鍵字和保留字(50個)。但是注意像java,Integer,sizeof,friendly等都不是Java的關(guān)鍵字

    d.標識符大小寫是敏感的,但沒有長度的限制。

    Switch(i)

      a.switch(i)中的參數(shù)最高精度是int(或者short,byte,char),但不可是long,float,double

      b.default語句可以放置于任何地方(default意為都不匹配case中的值)

      c.當(dāng)語句中未加break語句時,則程序會從匹配的地方開始執(zhí)行(包括匹配default語句),接下來所有的語句都會被執(zhí)行(而不管匹配否),直到遇到break語句或switch尾部。

    垃圾收集

      a.只要一個對象失去了所有的reference,就可以考慮收集到垃圾收集堆了。

      B.當(dāng)失去對一個對象的所有引用時,JVM只是考慮垃圾收集,但并不意味著就立刻收回這個對象的內(nèi)存,甚至根本不收回。JVM僅會在需要更多的內(nèi)存以繼續(xù)執(zhí)行程序時,才會進行垃圾收集。

    C.多數(shù)情況下,你永遠不會知道垃圾收集什么時候會發(fā)生。Java將垃圾收集進程作為一個低優(yōu)先級線程在運行。在Java中垃圾收集是不能被強迫立即執(zhí)行的。調(diào)用System.gc()或Runtime.gc()靜態(tài)方法不能保證垃圾收集器的立即執(zhí)行,因為,也許存在著更高優(yōu)先級的線程。

    D.如果你想人工調(diào)用垃圾收集,并想在收集對象時執(zhí)行一些你想要的任務(wù),你就可以覆蓋一個叫finalize()的方法。java會為每一個對象只調(diào)用一次finalize()方法。finalize()方法必須被申明為protected的,不返回任何值(viod),而且要申明拋出一個Throwable對象,并一定要調(diào)用超類的finalize()方法(super.finalize())。

       eg.protected void finalize() throws Throwable(){

             super.finalize();

             …………;}

    is a & has a

      is a  描述的是一個超類和一個子類的關(guān)系,也即是繼承的關(guān)系。

      has a 描述的是一個對象的部分是另一個對象,也即是組合的關(guān)系(或稱為調(diào)用)。

    內(nèi)類與匿名類

      內(nèi)類是被包含的類中類,有三個方面需要注意:一般內(nèi)類、方法內(nèi)類、靜態(tài)內(nèi)類。

      · 一般內(nèi)類它可以被當(dāng)做外類的一個“實例變量”來看待。因此,四個接入控制符public、protected、default、private。只是注意:要在外類的non-static函數(shù)外產(chǎn)生該內(nèi)類對象,必須以OuterClassName.InnerClassName的形式指定該內(nèi)類對象的類型申明。一般內(nèi)類必須得關(guān)聯(lián)至其外類的某個對象。

                    一般內(nèi)類不可擁有static成員。

    · 方法內(nèi)類它屬于范圍型內(nèi)類,也就是說你無法在方法外來調(diào)用內(nèi)類,從這一點來講它可視為方法的局部變量。但是,雖然有它的范疇性,畢竟內(nèi)類還是類,它不會像局部變量那樣隨著方法的返回就消失了,它仍舊被java視為類。

                  A.方法內(nèi)類可以直接訪問外類的任何成員

                  B.方法內(nèi)類只能訪問該方法中final型局部變量和final型的方法參數(shù)

                  C. 方法內(nèi)類不可有任何接入控制符修飾(這一點與局部變量相同)

      · 靜態(tài)內(nèi)類它在產(chǎn)生其對象時不需要存在一個外類對象。它可被視為static函數(shù)。

                 static內(nèi)類可以置于接口中。

      · 匿 名 類它實際上是繼承自new類的一個無名類。New傳回的reference會被自動向上轉(zhuǎn)型。匿名類不能擁有構(gòu)造器,但是可以通過其基類默認或帶參數(shù)的構(gòu)造器來申明。

    匿名類添加任何修飾符(遵循超類的修飾符),也不可實現(xiàn)接口、拋出異常。

    斷言

      斷言是Java 1.4中新添加的功能,是Java中的一種新的錯誤檢查機制,它提供了一種在代碼中進行正確性檢查的機制,但是這項功能可以根據(jù)需要關(guān)閉。斷言包括:assert關(guān)鍵字,AssertionError類,以及在java.lang.ClassLoader中增加了幾個新的有關(guān)assert方法。

    assert最重要的特點是assert語句可以在運行時任意的開啟或關(guān)閉,默認情況下是關(guān)閉的。

    斷言語句有兩種合法的形式:a.assert expression_r1; b.assert expression_r1 : expression_r2;

    expression_r1是一條被判斷的布爾表達式,必須保證在程序執(zhí)行過程中它的值一定是真;expression_r2是可選的,用于在expression_r1為假時,傳遞給拋出的異常AssertionError的構(gòu)造器,因此expression_r2的類型必須是合法的AssertionError構(gòu)造器的參數(shù)類型。AssertionError除了一個不帶參數(shù)的缺省構(gòu)造器外,還有7個帶單個參數(shù)的構(gòu)造器,分別為:object(eg.String)  boolean  char  int  long  float  double。第一種形式如果拋出異常,則調(diào)用AssertionError的缺省構(gòu)造器,對于第二種形式,則根據(jù)expression_r2值的類型,分別調(diào)用7種單參數(shù)構(gòu)造器中的一種。

    A.assert程序的編譯:javac -source 1.4 TestAssert.java(提示java按1.4版本編譯)

    B.assert程序的運行:java –ea TestAssert 或者 java –ea:TestAssert TestAssert

       其它的運行參數(shù):java -ea:pkg0... TestAssert;java –esa;java –dsa(系統(tǒng)類斷言),另外,還可以同時組合用。當(dāng)一個命令行使用多項 -ea -da 參數(shù)時,遵循兩個基本的原則:后面的參數(shù)設(shè)定會覆蓋前面參數(shù)的設(shè)定,特定具體的參數(shù)設(shè)定會覆蓋一般的參數(shù)設(shè)定

    C.AssertinError是Error的直接子類,因此代表程序出現(xiàn)了嚴重的錯誤,這種異常通常是不需要程序員使用catch語句捕捉的。

    D.使用assert的準則:assert語句的作用是保證程序內(nèi)部的一致性,而不是用戶與程序之間的一致性,所以不應(yīng)用在保證命令行參數(shù)的正確性。可以用來保證傳遞給private方法參數(shù)的正確性。因為私有方法只是在類的內(nèi)部被調(diào)用,因而是程序員可以控制的,我們可以預(yù)期它的狀態(tài)是正確和一致的。公有方法則不適用。此外,assert語句可用于檢查任何方法結(jié)束時狀態(tài)的正確性,及在方法的開始檢查相關(guān)的初始狀態(tài)等等。

    assert語句并不構(gòu)成程序正常運行邏輯的一部分,時刻記住在運行時它們可能不會被執(zhí)行。

    線程

      線程是將程序中容易消耗大量cpu且易陷入死循環(huán)的片斷代碼獨立出來作為一個線程來運行(也即線程是一個代碼塊)。

      線程一經(jīng)啟動start,就會進入ready狀態(tài)(實際上就是runnable狀態(tài),只是等待分配cpu)。這也說明線程并不會馬上就running,其運行具有不確定性。線程啟動后,只要不跳出run()方法,則一直都有機會running,它由系統(tǒng)自動在各線程間分配cpu時間來running。要牢記的是:線程運行與中斷具有不確定性,你永遠也不知道線程何時會運行,何時會中斷。

      線程從對象的角度來看,它自身也可以是一個對象。它可視為其它對象中的一個代碼塊。

      在線程的概念中要特別注意幾個概念:單線程、多線程多線程的運行多線程間的同步(資源訪問)多線程間的通信

      · 單線程 對于單線程而言,編寫其程序是比較簡單的,也比較容易理解,因為它并不涉及到synchronized和communication問題。創(chuàng)建單線程的方法有兩種,其一、擴展Thread類,即class A extends Thread{public void run(){};……};其二、實現(xiàn)Runnable接口,class B implements Runnable{Thread t=new Thread(this);public void run(){};……};

      · 多線程 相對于單線程而言,多線程會復(fù)雜很多,原因就是它們會涉及到多線程間的資源訪問多線程間通信問題。這就涉及到下面所說的三個方面:多線程的運行、多線程間的同步(資源訪問)、多線程間的通信

      · 多線程的運行 對于多個可運行runnable的線程來說,運行與中斷具有不確定性,永遠也無法知道線程何時會運行,何時會中斷。但是多線程運行也遵循幾個原則:如果多個線程具有同樣的優(yōu)先級,則系統(tǒng)會在它們之間切換cpu時間運行;JVM基于優(yōu)先級來決定線程的運行,但是這并不意味著一個低優(yōu)先級的線程一直不運行

      · 多線程的同步 被線程可訪問的每個對象都有一個僅被一個線程訪問控制的鎖,鎖控制著對對象的同步碼的存取。這個可被多個線程訪問的對象就是所說的資源共享問題。

    A.在程序中,可以通過定義一個synchronized代碼塊或多個synchronized方法來使得調(diào)用的線程獲得該對象的控制鎖。通過獲得對象的鎖,該線程就會阻止其它線程對該對象所定義的同步塊同步方法進行操作(特別注意的是,此時并不能保證其它線程對該對象的非同步變量和非同步方法進行操作)。

    B.線程只有在同步塊或同步方法返回后才釋放鎖。

    C.synchronized并不能保證程序的運行連續(xù)性,而只是保證同一性。也就是說即使在synchronized塊或方法中,線程的運行仍舊會有中斷的可能性。盡管如此,但它卻能確保別的線程不會再訪問該對象的其它同步塊和方法,因為對象鎖并未釋放。這一事實說明了“多線程的運行”與“多線程間的同步”是兩個獨立的概念。

    D.多線程的同步塊或方法可以放在任何可被線程訪問的對象中(包括線程本身,它實際上也可被其它的線程訪問)。

      · 多線程間的通信 多線程間的同步消除了一個線程在改變另一個線程的穩(wěn)定對象狀態(tài)時發(fā)生的并發(fā)錯誤,但是就線程間通信而言,同步不起任何作用,也就是說“多線程間的通信”又是一個獨立的概念。多線程間的通信通常是靠wait(),notify()兩個方法來實現(xiàn)的,有關(guān)這兩個方法的總結(jié)如下:

        1.wait(),notify()屬于object方法,并不是線程的方法

    2.object.wait()  意為:調(diào)用我(指該object)的當(dāng)前線程你得等等,也就是使...(調(diào)用我的當(dāng)前線程)...等待

    object.notify()意為:該喚醒其它先前調(diào)用過我的且在等待的線程

          從上述意義可知,wait(),notify()的對象是指線程所要用到的共享對象(當(dāng)然共享對象也可以是線程對象),但是它的方法動作卻是針對調(diào)用它的線程。(通常情況下,對象的方法是作用于自己的屬性,而很少作用于其它對象。若要作用于其它對象,則用調(diào)用object.method())

    3.wait(),notify()必須成對出現(xiàn),出現(xiàn)的方式可有3種形式。

          A.{wait();.... notify();}

          B.{wait();}... {object.notify();}

          C.{notify();}... {object.wait();}

    4.wait(),notify()必須出現(xiàn)在synchronized方法或塊中,否則會出現(xiàn)異常。原因是因為wait()會釋放對象鎖,而鎖必然是出現(xiàn)在同步方法或塊中。另外,wait()同sleep()一樣,也必須捕捉異常InterruptedException

    5.wait(),notify()的執(zhí)行一般與外在的條件有關(guān),只有條件改變了才觸發(fā)喚醒等待的線程。這種條件的改變通常是以旗標(Tag)的方式出現(xiàn),也即當(dāng)某一方法執(zhí)行完后,應(yīng)當(dāng)立即改變旗標值。假若需要讓線程交替執(zhí)行,則還需要加入互斥條件的判斷。eg.同步方法1中{if(a)},則同步方法2中{if(!a)}

    6.當(dāng)執(zhí)行完notify()時,程序并不會立即去運行調(diào)用wait()的線程,而直到釋放notify()的對象鎖。當(dāng)釋放完鎖后,程序重新分配cpu,要注意的是,此時系統(tǒng)并不一定就讓wait的線程去運行,而有可能是剛才調(diào)用notify()的線程接著繼續(xù)運行。這一點正說明了線程運行與中斷的不確定性。

    7.一般說來,notify()是喚醒等待池中等待時間最長的線程;而notifyAll()是喚醒等待池中所有等待線程,然后線程去競爭對象鎖。這里說的是一般情況,有時情況并非如此,這是由系統(tǒng)中線程運行與中斷的不確定性決定的。

    8.wait(),notify()通常情況下需要sleep()的配合,否則屏幕中的運行顯式會“飛速”。

    9.多線程間的通信會出現(xiàn)死鎖現(xiàn)象,即wait的線程有可能永遠也得不到對象鎖。

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

    其他注意問題

    ☆     數(shù)組

    a.?dāng)?shù)組在使用之前,必須要保證給其分配內(nèi)存(系統(tǒng)會用默認值初始化),不可只定義。否則編譯通過運行也會出現(xiàn)空指針錯誤。分配內(nèi)存只需通過new就可以了。

    b.二維數(shù)組的第二維可以是變長的,而且可以在定義時不指定具體值。這意味著java中的二維數(shù)組不必像矩陣那樣要求每一維長度都相同。

    ☆     變量賦值

    a.實例變量只可在定義時顯式賦值,不可先定義,再賦值(這樣的話編譯出錯)。

    b.方法變量既可以在定義時顯式賦值,又可以先定義以后再賦值。

    c.static變量可以在類的任何地方賦值(若在方法中賦值,實際上是重賦值了)。

    d.final變量可以在任何地方賦值,但是一旦賦值,就不允許再次重賦值。

    e.static final變量只能在定義處賦值(即:常量)。

    ☆     移位

    a.>>  首位的拷貝右移位。等同于有符號的除法。

    b.>>> 零填充右移位。

    c.<<  左移位。等同于有符號乘法,但是必須遵循整數(shù)的溢出原則。

    d.>>32 >>>32任何移多少位都是移模32的余數(shù)。eg.移32位即不移。

    ☆     byte、char和int

    由于char的取值范圍和int的正取值范圍相同,所以,整型字面量可以直接賦給char。但是要是明確將一個整型(int)變量直接賦給char變量則編譯錯誤。

    另外,int i=5;char c=’a’;c+=i;編譯是通過的。

    byte類型在強制轉(zhuǎn)型的情況下,當(dāng)范圍超出時會循環(huán)溢出。

    ☆     求模%

    求余只管左邊的符號,右邊不管。

    eg. int a=-5;int b=-2;System.out.println(a%b) //-1

       int a=-5;int b=2;System.out.println(a%b) //-1

       int a=5;int b=-2;System.out.println(a%b) //1

     

    posted on 2009-10-16 11:49 李云澤 閱讀(600) 評論(0)  編輯  收藏 所屬分類: 面試筆試相關(guān)的

    主站蜘蛛池模板: 麻豆亚洲av熟女国产一区二| 免费一看一级毛片全播放| 国产亚洲精品xxx| 亚洲免费一区二区| 国产亚洲情侣一区二区无码AV| 免费人成网上在线观看| 亚洲国产精品成人久久蜜臀| 日韩精品无码永久免费网站| 免费在线观看你懂的| 九九综合VA免费看| 亚洲一区无码精品色| a级毛片毛片免费观看久潮| 亚洲国产精品无码AAA片| 6080午夜一级毛片免费看 | 日韩免费在线中文字幕| 亚洲一区无码精品色| 免费成人在线视频观看| 99人中文字幕亚洲区| 在线看片无码永久免费视频| 亚洲熟女www一区二区三区| 国产三级免费电影| 一级日本高清视频免费观看| 国产亚洲一区二区三区在线| 99视频有精品视频免费观看| 亚洲一区二区三区在线网站| 国产一区二区三区免费在线观看| 香港经典a毛片免费观看看| 在线A亚洲老鸭窝天堂| 一区二区三区观看免费中文视频在线播放| 久久亚洲精品无码AV红樱桃| 国产99视频精品免费观看7| 男男黄GAY片免费网站WWW| 久久亚洲国产中v天仙www| 免费观看无遮挡www的视频| 亚洲国产精品无码观看久久| 国产91精品一区二区麻豆亚洲| 在线免费观看亚洲| 粉色视频在线观看www免费| 亚洲AV无码成人精品区天堂| 日韩免费视频播放| 日本卡1卡2卡三卡免费|