Java 基礎面經(二)

1 淺拷貝與深拷貝

關於 Java 中的對象克隆,有直接賦值、淺拷貝、深拷貝三種方式。

  1. 直接賦值:例如 Person a = new Person();Person b = a;,這種方法僅僅拷貝了對象引用地址,並沒有在內存中生成新的對象。
  2. 淺拷貝:如果原型對象的成員變量是值類型,將複製一份給克隆對象,也就是說在堆中擁有獨立的空間;如果原型對象的成員變量是引用類型,則將引用對象的地址複製一份給克隆對象,也就是說原型對象和克隆對象的成員變量指向相同的內存地址。換句話說,在淺克隆中,當對象被複制時只複製它本身和其中包含的值類型的成員變量,而引用類型的成員對象並沒有複製。要實現淺拷貝,我們只需要被複制類需要實現 Cloneable 接口,重寫 clone 方法即可。
  3. 深拷貝:相對於淺拷貝,深拷貝是一種完全拷貝,無論是值類型還是引用類型都會完完全全的拷貝一份,在內存中生成一個新的對象,簡單點說就是拷貝對象和被拷貝對象沒有任何關係,互不影響。深拷貝有兩種方式,一種是跟淺拷貝一樣實現 Cloneable 接口,另一種是實現 Serializable 接口,用序列化的方式來實現深拷貝。

2 什麼是反射?

java反射機制的理解

3 反射機制的優點與缺點?

  1. 優點:可以實現動態創建對象和編譯,體現出很大的靈活性,特別是在 J2EE 的開發中它的靈活性就表現的十分明顯。比如,一個大型的軟件,不可能一次就把把它設計的很完美,當這個程序編譯後,發佈了,當發現需要更新某些功能時,我們不可能要用戶把以前的卸載,再重新安裝新的版本,假如這樣的話,這個軟件肯定是沒有多少人用的。採用靜態的話,需要把整個程序重新編譯一次纔可以實現功能的更新,而採用反射機制的話,它就可以不用卸載,只需要在運行時才動態的創建和編譯,就可以實現該功能。
  2. 缺點:對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴 JVM,我們希望做什麼並且它滿足我們的要求。這類操作總是慢於只直接執行相同的操作。

靜態編譯:在編譯時確定類型
動態編譯:運行時確定類型,綁定對象。動態編譯最大限度的發揮了 java 的靈活性,體現了多態的應用,有利於降低類之間的耦合性。

4 java 元註解的作用?

元註解是 java API 提供,是專門用來定義註解的註解。java 一共有四個元註解:

  1. @Target 表示該註解用於什麼地方
  2. @Retention 表示在什麼級別保存該註解信息
  3. @Documented 將此註解包含在 javadoc 中 ,它代表着此註解會被 javadoc 工具提取成文檔。在 doc 文檔中的內容會因爲此註解的信息內容不同而不同
  4. @Inherited 允許子類繼承父類中的註解

5 jdk 自帶的註解?

  1. @Overried:告訴編譯器要檢查該方法是重寫父類的方法
  2. @Deprecated:標記某個類或方法等已經廢棄
  3. @SuppressWarnings:抑制編譯器警告
  4. @FunctionalInterface:用來指定該接口是函數式接口

6 char 型變量中能不能存貯一箇中文漢字,爲什麼?

可以。因爲 Java 中使用的編碼是 Unicode,一個 char 類型佔2個字節(16比特),所以放一箇中文是沒問題的。

7 兩個對象值相同(x.equals(y) == true),但卻可以有不同的 hashcode?

如果該對象重寫了 equals 方法,那麼可能會出現 equals 相同,但 hashcode 不同的情況,但假如沒有重寫 equals 方法,那麼它默認繼承是 Object 的 equals 方法,根據源碼可知,此時 equals 相同, hashcode 一定相同。

public boolean equals(Object obj) {
        return (this == obj);
}

需要注意的是,我們在開發的過程中,應保證 equals 相等的對象,hashcode 也必須相等。當重寫 equals 方法時有必要重寫 hashcode 方法,保證相等的對象有相等的哈希碼。

如果兩個對象相同(equals 方法返回 true),那麼它們的 hashCode 值一定要相同;如果兩個對象的 hashCode 相同,這兩個對象並不一定相同。

8 List<T>,List<?>,List<Object> 三者的區別?

建議採用的順序

9 BIO、NIO 和 AIO 的區別?

BIO、NIO和AIO的區別、三種IO的原理與用法

10 Integer 類的緩存機制?

Integer類的緩存機制

11 String 與 int 之間的轉換?

示例一

String str = "" + 100;
System.out.println(str);

示例二

String str = Integer.toString(100);
System.out.println(str);

示例三

String str = String.valueOf(100);
System.out.println(str);

重點來了!上面三種方法只有 String.valueOf() 方法會首先對轉換的對象進行判空檢測,如果爲空,則返回 “null” 字符串,以至於不會報出空指針異常。所以,在遇到字符串轉換的時候,首選 String.valueOf() 方法。

12 Java 位運算

  1. 左移( << ):5 << 2 = 20
  2. 右移( >> ) :5 >> 2 = 1(正數右移,高位用0補,負數右移,高位用1補)
  3. 無符號右移( >>> ) :使用 >> 會根據原來最高位符號位進行補位,而 >>> 會直接使用0進行補位,故其會由負數變成正數
  4. 位與( & ):第一個操作數的的第 n 位與第二個操作數的第 n 位如果都是1,那麼結果的第 n 位也爲1,否則爲0
  5. 位或( | ):第一個操作數的的第 n 位與第二個操作數的第 n 位只要有一個是1,那麼結果的第 n 位也爲1,否則爲0
  6. 位非( ~ ):第一個操作數的的第 n 位與第二個操作數的第 n 位相反,那麼結果的第 n 位也爲1,否則爲0
  7. 位異或( ^ ):操作數的第 n 位爲1,那麼結果的第 n 位爲0,反之

參考;Java 淺拷貝、深拷貝,你知多少?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章