面試整理(Java基礎1)

1、面向對象的特徵有哪些方面?

抽象:
是一種將一類對象的相同特徵的部分抽取出來構建的過程,分爲行爲抽象和數據抽象兩種,抽象只關注對象的屬性和特徵並不關心行爲的細節問題。
數據抽象:就是用代碼的形式,表示現實世界中一類事物的特性,比如人的姓名,年齡等,抽象出來一般叫做屬性或者成員變量等。
行爲抽象:就是用代碼的形式,表示現實世界中事物的一系列行爲,比如人可以喫飯等,抽象出來一般叫做方法。

封裝:
把數據和操作數據的方法綁定封閉起來,對數據的訪問只能通過已定義暴露的接口進行訪問。面向對象的本質就是將現實世界描繪成一系列完全自治、封閉的對象。

多態:
同一操作作用於不同的對象,可以有不同的解釋,產生不同的執行結果。再java中可以說,接口的多種不同的實現方式即爲多態。

繼承
繼承可以使得子類別具有父類別的各種屬性和方法,而不需要再次編寫相同的代碼。子類別繼承父類別的同時,可以重新定義某些屬性,並重寫某些方法,即覆蓋父類別的原有屬性和方法,使其獲得與父類別不同的功能。

2、訪問修飾符 public,private,protected,以及不寫(默認)時的區別?

類的成員不寫訪問修飾時默認爲 default這裏是引用

3、String 是最基本的數據類型嗎?

不是。String屬於引用數據類型。Java 中的基本數據類型只有 8 個 :byte、short、int、long、float、double、char、boolean。其他的都是引用數據類型包括枚舉類型等。
 
基本數據類型在被創建時,在棧上給其劃分一塊內存,將數值直接存儲在棧上。
 
引用數據類型在被創建時,首先要在棧上給其引用(句柄)分配一塊內存,而對象的具體信息都存儲在堆內存上,然後由棧上面的引用指向堆中對象的地址。
 
在數據做爲參數傳遞的時候,基本數據類型是值傳遞,而引用數據類型是引用傳遞(地址傳遞)。

4、float f=3.4;是否正確?

不正確。因爲java小數默認是雙精度類型(double),將雙精度型(double)賦值給浮點型(float)屬於下轉型(也稱爲窄化)會造成精度損失。

5、short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?

第一個是錯誤的,第二個正確。再s1 + 1的時候會自動轉換成int類型。所以會造成編譯時錯誤。而s1 += 1相當於s1 = (short)(s1 + 1)強制類型轉換了一下所以沒有錯誤。

6、int 和 Integer 有什麼區別?

int是基本數據類型,integer是封裝數據類型。int默認值爲0.integer默認值爲null。
 
爲了編程的方便還是引入了基本數據類型,但是爲了能夠將這些基本數據類型當成對象操作,Java 爲每一個基本數據類型都引入了對應的包裝類型(wrapper class),int 的包裝類就是 Integer,從 Java 5 開始引入了自動裝箱/拆箱機制,使得二者可以相互轉換。

class AutoUnboxingTest {
	public static void main(String[] args) {
		Integer a = new Integer(3);
		Integer b = 3;
		// 將 3 自動裝箱成 Integer 類型
		int c = 3;
		System.out.println(a == b);
		// false 兩個引用沒有引用同一對
		象
		System.out.println(a == c);
		// true a 自動拆箱成 int 類型再和 c
		比較
	}
}
public class Test03 {
	public static void main(String[] args) {
		Integer f1 = 100, f2 = 100, f3 = 150, f4 = 150;
		System.out.println(f1 == f2);//會輸出true
		System.out.println(f3 == f4);//會輸出false
	}
}

如果不明就裏很容易認爲兩個輸出要麼都是 true 要麼都是 false。首先需要注意的是 f1、f2、f3、f4 四個變量都是
Integer 對象引用,所以下面的==運算比較的不是值而是引用。裝箱的本質是什麼呢?當我們給一個 Integer 對象賦一個 int
值的時候,會調用 Integer 類的靜態方法 valueOf,如果看 valueOf 的源代碼就知道發生了什麼。

public static Integer valueOf(int i) {
	if (i >= IntegerCache.low && i <= IntegerCache.high)
	return IntegerCache.cache[i + (-IntegerCache.low)];
	return new Integer(i);
}

IntegerCache 是 Integer 的內部類,其代碼如下所示

/**
* Cache to support the object identity semantics of autoboxing for
values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>}
option.
* During VM initialization, java.lang.Integer.IntegerCache.high
property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
	static final int low = -128;
	static final int high;
	static final Integer cache[];
	static {
		// high value may be configured by property
		int h = 127;
		String integerCacheHighPropValue =
		sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
		if (integerCacheHighPropValue != null) {
			try {
				int i = parseint(integerCacheHighPropValue);
				i = Math.max(i, 127);
				// Maximum array size is Integer.MAX_VALUE
				h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
			}
			catch( NumberFormatException nfe) {
				// If the property cannot be parsed into an int,
				ignore it.
			}
		}
		high = h;
		cache = new Integer[(high - low) + 1];
		int j = low;
		for (int k = 0; k < cache.length; k++)
		cache[k] = new Integer(j++);
		// range [-128, 127] must be interned (JLS7 5.1.7)
		assert IntegerCache.high >= 127;
	}
	private IntegerCache() {
	}
}

簡單的說,如果整型字面量的值在-128 到 127 之間,那麼不會 new 新的 Integer對象,而是直接引用常量池中的 Integer 對象,所以上面的面試題中 f1f4 的結果是 false。

7、&和&&的區別?

&運算符有兩種用法:(1)按位與;(2)邏輯與。
 
&&運算符是短路與運算。邏輯與跟短路與的差別是非常巨大的,雖然二者都要求運算符左右兩端的布爾值都是true 整個表達式的值纔是 true。
 
&&之所以稱爲短路運算是因爲,如果&&左邊的表達式的值是 false,右邊的表達式會被直接短路掉,不會進行運算。很多時候我們可能都需要用&&而不是&,
 
例如在驗證用戶登錄時判定用戶名不是 null 而且不是空字符串,應當寫爲:username != null &&!username.equals(“”),二者的順序不能交換,更不能用&運算符,因爲第一個條件如果不成立,根本不能進行字符串的 equals 比較,否則會生 NullPointerException 異常。
 
注意:邏輯或運算符(|)和短路或運算符(||)的差別也是如此。

8、解釋內存中的棧(stack)、堆(heap)和方法區(method area)的用法。

9、Math.round(11.5) 等於多少?Math.round(-11.5)等於多少?

Math.round(11.5)的返回值是 12,Math.round(-11.5)的返回值是-11。四捨五入取整。

10、switch 是否能作用在 byte 上,是否能作用在 long 上,是否能作用在 String 上?

從 Java 7 開始,可以是字符串(String),但是長整型(long)在目前所有的版本中都是不可以的。

11、用最有效率的方法計算 2 乘以 8?

2 << 3(左移 3 位相當於乘以 2 的 3 次方,右移 3 位相當於除以 2 的 3 次方)。

12、數組有沒有 length()方法?String 有沒有 length()方法?

數據是length屬性。String有length()方法。

13、在 Java 中,如何跳出當前的多重嵌套循環?

在最外層循環前加一個標記如 A,然後用 break A;可以跳出多重循環。(Java 中支持帶標籤的 break 和 continue 語句)

14、構造器(constructor)是否可被重寫(override)?

不能,應爲構造器不能被繼承,但是可以被重載。

15、兩個對象值相同(x.equals(y) == true),但卻可有不同的 hashcode,這句話對不對?

不對。如果兩個對象的值相同則hashcode一定相同,相反如果兩個對象的hashcode相同,他們的值不一定相同。
Java 對於 eqauls 方法和 hashCode 方法是這樣規定的:
(1)如果兩個對象相同(equals 方法返回 true),那麼它們的 hashCode 值一定要相同;
(2)如果兩個對象的 hashCode 相同,它們並不一定相同。
 
首先 equals 方法必須滿足
自反性(x.equals(x)必須返回 true)、
對稱性(x.equals(y)返回 true 時,y.equals(x)也必須返回 true)、
傳遞性(x.equals(y)和 y.equals(z)都返回 true 時,x.equals(z)也必須返回 true)
一致性(當 x 和 y 引用的對象信息沒有被修改時,多次調用 x.equals(y)應該得到同樣的返回值),
而且對於任何非 null 值的引用 x,x.equals(null)必須返回 false。
實現高質量的 equals 方法的訣竅包括:
(1) 使用==操作符檢查”參數是否爲這個對象的引用”;
(2) 使用 instanceof 操作符檢查”參數是否爲正確的類型”;
(3) 對於類中的關鍵屬性,檢查參數傳入對象的屬性是否與之相匹配;
(4) 編寫完 equals方法後,問自己它是否滿足對稱性、傳遞性、一致性;
(5) 重寫 equals 時總是要重寫 hashCode;
(6) 不要將 equals 方法參數中的 Object 對象替換爲其他的類型,在重寫時不要忘掉@Override 註解。

16、是否可以繼承 String 類?

不能,因爲String是被final修飾的

17、當一個對象被當作參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裏到底是值傳遞還是引用傳遞?

是值傳遞,Java 語言的方法調用只支持參數的值傳遞。

18、String 和 StringBuilder、StringBuffer 的區別?

String 是隻讀字符串,也就意味着 String 引用的字符串內容是不能被改變的
而 StringBuffer/StringBuilder 類表示的字符串對象可以直接進行修改。
StringBuffer是線程安全的。StringBuilder沒有被synchronized修飾是現成不安全的

public static void main(String[] args) {
        String s1 = "Programming";
        String s2 = new String("Programming");
        String s3 = "Program";
        String s4 = "ming";
        String s5 = "Program" + "ming";
        String s6 = s3 + s4;
        System.out.println(s1 == s2);//false
        System.out.println(s1 == s5);//true
        System.out.println(s1 == s6);//false
        System.out.println(s1 == s6.intern());//true
        System.out.println(s2 == s2.intern());//false
    }
// (1)String 對象的 intern 方法會得到字符串對象在常量池中對應的版本的引用
//(如果常量池中有一個字符串與 String 對象的 equals 結果是 true),
// 如果常量池中沒有對應的字符串,則該字符串將被添加到常量池中,然後返回常量池中字符串的引用;
// (2)字符串的+操作其本質是創建了 StringBuilder 對象進行 append 操作,
// 然後將拼接後的 StringBuilder 對象用toString 方法處理成 String 對象,
//這一點可以用 javap -c StringEqualTest.class命令獲得 class 文件對應的 JVM 字節碼指令就可以看出來。

19、重載(Overload)和重寫(Override)的區別。重載的方法能否根據返回類型進行區分?)

方法的重載和重寫都是實現多態的方式
 
重載發生在一個類中,同名的方法如果有不同的參數列表(參數類型不同、參數個數不同或者二者都不同)則視爲重載;
重載是指不同的函數使用相同的函數名,但是函數的參數個數或類型不同。調用的時候根據函數的參數來區別不同的函數
 
重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對返回類型沒有特殊的要求。
是指在派生類中重新對基類中的虛函數(注意是虛函數)重新實現。即函數名和參數都一樣,只是函數的實現體不一樣。

1、重載的規則:
①必須具有不同的參數列表。
②可以有不同的訪問修飾符。
③可以拋出不同的異常。
2、重寫方法的規則:
①參數列表必須完全與被重寫的方法相同,否則不能稱其爲重寫而是重載。
②返回的類型必須一直與被重寫的方法的返回類型相同,否則不能稱其爲重寫而是重載。
③訪問修飾符的限制一定要大於被重寫方法的訪問修飾符。
④重寫方法一定不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的檢查型異常。
三、類的關係上的區別:
重寫是子類和父類之間的關係,是垂直關係;重載是同一個類中方法之間的關係,是水平關係。

面試整理(Java基礎2)

轉載自:https://juejin.im/post/5de8c6c5f265da33d74418d7

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