java 基礎深入

iteye_9849發表於2009-10-28

父類引用指向子類物件:

 從物件的記憶體角度來理解試試.
假設現在有一個父類Father,它裡面的變數需要佔用1M記憶體.有一個它的子類Son,它裡面的變數需要佔用0.5M記憶體.
現在通過程式碼來看看記憶體的分配情況:
Father f = new Father();//系統將分配1M記憶體.
Son s = new Son();//系統將分配1.5M記憶體!因為子類中有一個隱藏的引用super會指向父類例項,所以在例項化子類之前會先例項化一個父類,也就是說會先執行父類的建構函式.由於s中包含了父類的例項,所以s可以呼叫父類的方法.
Son s1 = s;//s1指向那1.5M的記憶體.
Father f1 = (Father)s;//這時f1會指向那1.5M記憶體中的1M記憶體,即是說,f1只是指向了s中例項的父類例項物件,所以f1只能呼叫父類的方法(儲存在1M記憶體中),而不能呼叫子類的方法(儲存在0.5M記憶體中).
Son s2 = (Son)f;//這句程式碼執行時會報ClassCastException.因為f中只有1M記憶體,而子類的引用都必須要有1.5M的記憶體,所以無法轉換.
Son s3 = (Son)f1;//這句可以通過執行,這時s3指向那1.5M的記憶體.由於f1是由s轉換過來的,所以它是有1.5M的記憶體的,只是它指向的只有1M記憶體.

 

多型:

多型性是指統一的介面,不同的表現形式。

總結:多型--》父類或者介面型別的引用指向子類或者實現該介面的類的物件..(多型是個執行時的行為..體現父與子的關係)

Java根據動態繫結決定執行“更具體”的方法,即子類方法。

http://liyanhui.iteye.com/blog/167853

 

2.對final型別的成員變數的初始化方式

   1.生明變數時直接賦值

   2.在生構造方法中完成賦值,如果一個類有多個構造方法,就要保證在每個構造方法中都要完成對該final型別變數的初始化工作

   3.對於final型別的引用變數來說,所謂的不能改變指的是該引用不能改變,但該應用所指向的物件的類容就可以該變的

 

三,一個類的宣告可否既是abstract 又是final型別的呢?

    abstract 要求當前類被繼承。而final不能被繼承。。矛盾。了。。

四,pubic final型別的變數為什麼一般都加上static呢?

  public class Test

{

   public static final str='aa';

}

   這樣寫的好處是節省記憶體。不加static的話。。如果Test有個100個變數的話就會在記憶體中有100個str的拷貝。加上了static只會有一個。。。

五。 ==  和equals的區別

   不要簡單的說。。==比較記憶體地址。。equals比較的是內容。---》這是對String

  而對Object來說equals 其實還是比較的記憶體地址。。這是因為String 和Object的equals的實現是不一樣的。。

六。HashSet ...

     當向集合set中增加物件時。首先集合計算要增加物件的hashCode碼,根據該值來得到一個位置用來存放當前的物件,當在該位置沒有一個物件存在的話,那麼集合set認為物件在集合不存在,直接增加進去。如果在該位置有一個物件存在的話,接著將準備增加到集合的物件與該位置上的物件進行equals方法比較,如果該equals方法返回false,那麼集合認為集合中不存在該物件,再進行一次雜湊,將該物件放到雜湊後計算出的地址裡,如果equals方法返回true,那麼集合認為集合中已經存在該物件了,不會再將該物件增加到集合中了。。

  對於於Object型別來說。。hashCode就是該物件的記憶體地址。。

 通常重寫equals方法時,必須重寫hashCode方法,如果一個類的兩個物件,使用equals方法比較時,結果為true,那麼該兩個物件必須具有相同的hashcode

七。Arraylist linkedlist vector的區別?

      Arraylist底層是用陣列來實現的。,底層會生成一個長度為10的陣列來存放物件。。

     Vector 底層也是用陣列來實現的。

    Arraylist的所有方法都不是同步的,,對於Vector。。大部分的public方法是同步的。。

   對於Arraylist ,查詢速度非常快,增加和刪除操作非常慢。(本質上是由陣列的特點來決定的)

   LinkedList底層是用雙向連結串列業實現的。。查詢速度非常的慢..,增加和冊除是非常的快的(本質是由雙向連結串列業實現的)

八。關於匿名內部類:該類一定是繼承了某個父類或實現了某個介面

九。泛形中。。的 ?等價於 ? extnds Object

十。簡單的單態的實現:

     pubic class Singleton

{

     private static Singleton sigleton =new Singleton();

 

     private Singleton(){}  //防止外面NEW

 

     public static Singleton getInstance()  

     {

       return  sigleton;

     }

十一。關於wait,notify,notifyAll以及sleep方法的關係

        1.如果一個執行緒呼叫了某個物件的wait方法,那麼該執行緒首先必須要擁有該物件的鎖(換句話說,一個執行緒如果呼叫了某個物件的wait方法,那麼該wait 方法必須要在synchronized中)

       2.如果一個執行緒呼叫了某個物件的wait方法,那麼該執行緒就會釋放物件的鎖

       3.在java物件中,有兩種池(鎖池,等待池)

       4.如果一個執行緒呼叫了某個物件的wait方法,那麼該執行緒進入該物件的等待池中(釋放鎖),如果未來某一時刻,另外一個執行緒呼叫了相同的物件的notify或者notifyAll方法,那麼在該等待池中的等待的執行緒就會起來進入該物件的鎖池中,去等待獲得該物件的鎖,如果獲得鎖成功後,那麼執行緒將沿著wait方法之後的路徑去執行。

       5.sleep(long time),如果一個執行緒呼叫了sleep方法睡眠,那麼在睡眠的同時,它不會失去物件的鎖的擁有權。

十二。關於synchronized關鍵字的作用

     1.在某個物件的所有synchronized方法中,在某一時刻,只能有一個唯一的一個執行緒去訪問這些synchronized方法

     2.如果一個方法是synchronzied方法,那麼該synchronized關鍵字表示給當前物件上鎖(即this)

     3.如果一個synchronized方法是靜態(static),那麼該synchronized關鍵字表示給當前物件所對應的Class物件上鎖.(每個類,不管生成多少物件,其對應的Class物件只有一個)

十三。關於初始化階段:servlet 有幾種初始化方式呢?

     1.客戶端第一次訪問該servlet,那麼該servlet將被例項化

      2.可以通過在web.xml檔案中,配置servlet的啟動引數,讓伺服器啟動後,該servlet自動完成例項化.

 

 十四。Iterator 的刪除問題?

 

  eg:  list<String> list=new ArrayList<String>();

         list.add("aa");

         list.add(''bb');

         list.add("aabb");

 

        for(Iterator it=list.itrator();it.hasNest();)

         {

            it.remove();// 這樣可以正常刪除的

            list.remove()//會報異常  (注要與itrator的內部實現有關的)

         }

  十四。Socket程式設計總結

     使用ServerSocket 和Socket實現伺服器端和客戶端的Socket通訊

    總結:1)建立Socket連線2)獲得輸入/輸出流3)讀/寫資料4)關閉輸入/輸出流5)關閉Socket

 十五.陣列的定義

       String [] arr = null;//表示定義陣列。
 String [] arr = new String[10];//表示建立陣列。
 Integer [] a = new Integer[]{1,2,3};//建立陣列並賦值
 String [][] two = new String[4][5]; //二維陣列建立。
 String [][] two = {{"A","b"},{"c","d"}};//二維陣列初始化
 int[][][] b = {
          {{1,2,3},{1,2,3}},
            {{3,4,1},{2,3,4}}
               };
 //多維陣列

16.runtimeException 和checked Excepton的理解:

從邏輯的角度來說,checked exceptions和runtime exception是有不同的使用目的的。checked exception用來指示一種呼叫方能夠直接處理的異常情況。而runtime exception則用來指示一種呼叫方本身無法處理或恢復的程式錯誤。

checked exception迫使你捕獲它並處理這種異常情況。以java.net.URL類的構建器(constructor)為例,它的每一個構建器都會丟擲MalformedURLException。MalformedURLException就是一種checked exception。設想一下,你有一個簡單的程式,用來提示使用者輸入一個URL,然後通過這個URL去下載一個網頁。如果使用者輸入的URL有錯誤,構建器就會丟擲一個exception。既然這個exception是checked exception,你的程式就可以捕獲它並正確處理:比如說提示使用者重新輸入。

ArrayIndexOutOfBoundsException(因為陣列numbers的成員是從0到2)。對於這個異常,呼叫方無法處理/糾正。

runtime exception用來指示一種呼叫方本身無法處理/恢復的程式錯誤。而程式錯誤通常是無法在執行過程中處理的,必須改正程式程式碼

 

17.執行緒:http://java.chinaitlab.com/line/768283_4.html

18. io   http://edu.codepub.com/2010/0623/23718.php

 

 

Java IO 的一般使用原則 : 

一、按資料來源(去向)分類:

1 、是檔案: FileInputStream, FileOutputStream, ( 位元組流 )FileReader, FileWriter( 字元 )

2 、是 byte[] : ByteArrayInputStream, ByteArrayOutputStream( 位元組流 )

3 、是 Char[]: CharArrayReader, CharArrayWriter( 字元流 )

4 、是 String: StringBufferInputStream, StringBufferOuputStream ( 位元組流 )StringReader, StringWriter( 字元流 )

5 、網路資料流: InputStream, OutputStream,( 位元組流 ) Reader, Writer( 字元流 )

二、按是否格式化輸出分:

1 、要格式化輸出: PrintStream, PrintWriter

三、按是否要緩衝分:

1 、要緩衝: BufferedInputStream, BufferedOutputStream,( 位元組流 ) BufferedReader, BufferedWriter( 字元流 )

四、按資料格式分:

1 、二進位制格式(只要不能確定是純文字的) : InputStream, OutputStream 及其所有帶 Stream 結束的子類

2 、純文字格式(含純英文與漢字或其他編碼方式); Reader, Writer 及其所有帶 Reader, Writer 的子類

五、按輸入輸出分:

1 、輸入: Reader, InputStream 型別的子類

2 、輸出: Writer, OutputStream 型別的子類

六、特殊需要:

1 、從 Stream 到 Reader,Writer 的轉換類: InputStreamReader, OutputStreamWriter

2 、物件輸入輸出: ObjectInputStream, ObjectOutputStream

3 、程式間通訊: PipeInputStream, PipeOutputStream, PipeReader, PipeWriter

4 、合併輸入: SequenceInputStream

5 、更特殊的需要: PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader

 

 

wait() 必須在synchronized 函式或者程式碼塊裡面
// wait()會讓已經獲得synchronized 函式或者程式碼塊控制權的Thread暫時休息,並且喪失控制權
// 這個時候,由於該執行緒喪失控制權並且進入等待,其他執行緒就能取得控制權,並且在適當情況下呼叫notifyAll()來喚醒wait()的執行緒。
// 需要注意的是,被喚醒的執行緒由於已經喪失了控制權,所以需要等待喚醒它的執行緒結束操作,從而才能重新獲得控制權。
//
// 所以wait()的確是馬上讓當前執行緒喪失控制權,其他的執行緒可以乘虛而入。
//
// 所以wait()的使用,必須存在2個以上執行緒,而且必須在不同的條件下喚醒wait()中的執行緒。

 

 

 

 

相關文章