1. 程式人生 > >Java基礎常識(適用於面試)

Java基礎常識(適用於面試)

  1. 八大資料型別的對應類裡有常量表示型別的最大值最小值等取值範圍
  2. 區域性變數不能被宣告為 static 變數
  3. final 物件的引用不能改變,但是裡面的值可以改變
  4. 類中的 final 方法可以被子類繼承,但是不能被子類修改
  5. final 類不能被繼承
  6. 如果一個類包含抽象方法,那麼該類一定要宣告為抽象類
  7. volatile:使兩個不同的執行緒總是看到某個成員變數的同一個值
  8. 介面可多重繼承介面(extends)
  9. 普通的類方法是可以和類名同名的,和構造方法唯一的區分就是,構造方法沒有返回值。
  10. 物件陣列預設是填充null,基本型別是有值的
  11. 啟動一個執行緒使用的是start而不是run方法
  12. 守護執行緒最典型的應用就是 GC (垃圾回收器)
  13. 全域性變數主動初始化,基本型別為0,引用型別為null。區域性變數需要手動初始化,否則不能通過編譯
  14. Java中沒有引用傳遞只有值傳遞,傳遞的是值的拷貝,也就是說傳遞後就互不相關了
    1. “在Java裡面引數傳遞都是按值傳遞”這句話的意思是:按值傳遞是傳遞的值的拷貝,按引用傳遞其實傳遞的是引用的地址值,所以統稱按值傳遞。
    2. 在Java裡面只有基本型別和按照下面這種定義方式的String是按值傳遞,其它的都是按引用傳遞。就是直接使用雙引號定義字串方式:String str = “Java私塾”;
  15. transient關鍵字只能修飾變數(本地變數是不能被transient關鍵字修飾的),被修飾的變數將不再是物件持久化的一部分,一個靜態變數不管是否被transient修飾,均不能被序列化。為什麼要禁止某些變數序列化,譬如一些敏感資訊在網路上傳輸。Externalizable介面也可以序列化物件,但是要重寫其序列化方法,且跟transient無關
  16. 繼承是子類使用父類的方法,而多型則是父類使用子類的方法。
  17. override是重寫(覆蓋)了一個方法,以實現不同的功能。重寫(覆蓋)的規則:
    1. 重寫方法的引數列表必須完全與被重寫的方法的相同,否則不能稱其為重寫而是過載.
    2. 重寫方法的訪問修飾符一定要大於被重寫方法的訪問修飾符(public>protected>default>private)
    3. 重寫的方法的返回值必須和被重寫的方法的返回一致
    4. 重寫的方法所丟擲的異常必須和被重寫方法的所丟擲的異常一致,或者是其子類
    5. 被重寫的方法不能為private,否則在其子類中只是新定義了一個方法,並沒有對其進行重寫
    6. 靜態方法不能被重寫為非靜態的方法(會編譯出錯)
  18. overload是過載,一般是用於在一個類內實現若干過載的方法,這些方法的名稱相同而引數形式不同
  19. 物件比較使用equals方法
  20. 普通方法可以和類同名,但必須顯示指定返回值(void也可以)。不過最好不要這麼做。
  21. 物件陣列未初始化預設是null,基本型別譬如int預設是0
  22. 執行緒分為守護執行緒和非守護執行緒(又叫使用者執行緒)。GC為守護執行緒
  23. volatile關鍵字用在多執行緒同步中,他不能保證執行緒安全,JVM只是保證從主記憶體中載入到執行緒工作記憶體中的值是最新的讀取值。
  24. 介面描述系統對外提供的所有服務,所以其成員必須是public的;介面的方法必須是抽象的;介面不能被例項化,所以沒有構造方法,沒有例項變數,只有靜態變數且未final的不可變(常量)。介面是為了提供統一的抽象,既然統一,就要求裡面的東西只能被實現而不能改。
  25. Java建立物件的四種方法:
    1. 使用new關鍵字
    2. 使用反射,呼叫java.lang.Class或者java.lang.reflect.Constructor類的newInstance()例項方法。
    3. 呼叫物件的clone()方法。
    4. 運用反序列化手段,呼叫java.io.ObjectInputStream物件的 readObject()方法
  26. 預設ArrayList的長度是10個,如果在new的時候加上引數例如ArrayList list = new ArrayList(20),那麼會一次性分配20。如果未指定,則從10個擴充1.5倍到15個。。
  27. public class NULL {
        public static void haha(){
         	System.out.println("haha");
        }
        public static void main(String[] args) {
            ((NULL)null).haha();
        } 
    }
這個程式碼是合法的,但null強制轉換後是無效物件,其返回值還是為null。但這裡呼叫的是類的靜態方法,所以是有效的
  1. 靜態塊和變數是在JVM載入類的時候執行的。靜態變數和靜態初始化塊是依照他們在類中的定義順序進行初始化的。同樣,變數和初始化塊也遵循這個規律。類例項化的初始化順序依次是(靜態變數、靜態初始化塊)>(變數、初始化塊)>構造器。如果有繼承那麼是:(父類靜態變數、父類靜態塊)>(子類靜態變數、子類靜態塊)>(父類變數、父類初始化塊)>(父類構造方法)>(子類變數、子類初始化塊)>(子類構造方法)。其中括號內的優先順序相同,在程式碼前面的先執行。
  2. 一般將父類異常類即Exception老大放在catch語句塊的最後一個,因為子類異常也會匹配父類異常。catch中子類在前,父類在後
  3. RandomAccessFile是IO包的類,但是其自成一派,從Object直接繼承而來。
  4. switch case中,記得加break
  5. 抽象類遵循的原則:
    1. abstract只能修飾類和方法,不能修飾字段
    2. 抽象類不能被例項化,只能被繼承
    3. 抽象方法不能做實現
    4. 含有抽象方法的類必須定義為抽象類
    5. 抽象類裡的方法被繼承後可以選擇性的實現,而介面則必須全部實現
    6. 抽象類是is-a的關係,藉口是has-a的關係
    7. 介面預設成員變數是public static的,而抽象類是friendly的(其實類中只要不指定訪問修飾符,都是friendly的)
  6. 子類被例項化時,會預設呼叫父類的無參構造引數(無論子類是否帶引數)。如果沒有建構函式,編譯器會給你加個無參建構函式。如果你自己寫了帶引數的建構函式,那麼編譯器不會給你新增無參建構函式。此時如果你不顯示的呼叫父類建構函式(super),那麼編譯出錯
  7. 多型的運用,見如下程式碼(當呼叫了父類建構函式的時候,子類的初始化還沒有開始,所以其成員變數還是null值)
public class Dervied extends Base {

    private String name = "dervied";

    public Dervied() {
        tellName();
        printName();
    }
    
    public void tellName() {
        System.out.println("Dervied tell name: " + name);
    }
    
    public void printName() {
        System.out.println("Dervied print name: " + name);
    }

    public static void main(String[] args){
        
        new Dervied();    
    }
}

class Base {
    
    private String name = "base";

    public Base() {
        tellName();
        printName();
    }
    
    public void tellName() {
        System.out.println("Base tell name: " + name);
    }
    
    public void printName() {
        System.out.println("Base print name: " + name);
    }
}
  1. Vector和ArrayList的區別:
    1. ArrayList在記憶體不夠時預設是擴充套件50% + 1個,Vector是預設擴充套件1倍。
    2. Vector提供indexOf(obj, start)介面,ArrayList沒有。
    3. Vector屬於執行緒安全級別的,但是大多數情況下不使用Vector,因為執行緒安全需要更大的系統開銷。
  2. System.gc()是建議呼叫gc 不保證呼叫時間 作用還是有的
  3. import static ,這個是靜態匯入,可以直接把某個類的靜態方法導進來用,如:import static org.junit.Assert.*;這樣,我們就可以直接在類中使用assertEquals方法了
  4. 在java的浮點型運算中:正浮點/0,結果為Infinity, 表示無窮大;負浮點/0,結果為-Infinity,表示無窮小。如果是整型/0 那會丟擲異常。這就是為什麼浮點運算可以除以0.
  5. Externalizable介面繼承了Serializable介面,擴充套件了writeExternal和readExternal方法,這兩個方法分別傳入了一個ObjectOutput和ObjectInput,用於實現具體的序列化,所以該介面可以確定哪些屬性被序列化,哪些又不需要序列化。值得注意的是,output和input的屬性順序必須一致。
  6. RMI預設埠為1099。RMI依賴於Java遠端訊息交換協議JRMP(Java Remote Messaging Protocol),該協議為java定製,要求服務端與客戶端都為java編寫。由於方法引數與返回值最終都將在網路上傳輸,故必須是可序列化的。
  7. Object.hashcode()方法是個native方法,具體實現被隱藏。根據網友使用c++測試,返回的不一定是記憶體地址,取決於具體執行環境(android windows 以及Oracle jdk open jdk)
  8. doublefloat不會出現資料誤差,而floatdouble有誤差:127.1f轉double為127.0999984741211。如果需要無誤差的轉,使用BigDecimal。
  9. List<String> list = new ArrayList<>();後面的<String>,可以省略String。
  10. String物件與字元字面量的equals,可以使用java.util.Objects#equals方法
  11. 對於 Integer var = ? 在-128 至 127 範圍內的賦值, Integer 物件是在IntegerCache.cache 產生,會複用已有物件,這個區間內的 Integer 值可以直接使用==進行判斷,但是這個區間之外的所有資料,都會在堆上產生,並不會複用已有物件,推薦使用 equals 方法進行判斷