1. 程式人生 > >javaSE面試題(精簡版)

javaSE面試題(精簡版)

一、java的跨平臺原理

1、什麼是平臺

把CPU處理器與作業系統的整體叫平臺

2、java跨平臺原理

java虛擬機器JVM將java檔案編譯成位元組碼檔案,也就是.class檔案,然後執行到不同的平臺,對應的系統會將位元組碼檔案轉換成對應平臺的對應機器碼,產生可執行性檔案

二、氣泡排序

1、概念

N個數字來比較,兩兩比較小靠前,外層迴圈N-1,內層迴圈N-1-i;

2、手寫程式碼

public class MrpSort{
	public static void main(String[] args){
		int[] arr = {1,4,
9,10,45,12,2}; for(int i=0;i<arr.length-1;i++){ for(int j=0;j<arr.length-1-i;j++){ if(arr[j]>arr[j+1]){ //交換 int temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } //遍歷陣列 for(int a:arr){ System.out.println(a); } } }

三、比較排序

1、概念

外層迴圈, 決定比較的輪次, 決定每輪需要確定的元素的下標,內層迴圈, 決定每輪比較時, 用於和i進行比較的下標的起止(打擂臺的方式)

2、手寫程式碼

package com.array.sort;

/**
 * 比較排序
 * @author Administrator
 *
 */
public class Comparison {

	public static void main(String[] args) {
		
		//宣告陣列中
		int[] arr = new int[20];
		//遍歷陣列, 隨機生成元素內容
		for (int i = 0; i < arr.length; i++) {
			//生成1~100的隨機數
			arr[i] = (int) (Math.random()*100 + 1);
		}
//輸出初始內容 System.out.println("原陣列內容如下:"); for (int i = 0; i < arr.length; i++) { //輸出元素內容 System.out.print(arr[i] + "\t"); //判斷是否換行 if(i%5 == 4) { //(i+1)%5==0 System.out.println(); } } System.out.println("==========================================="); /* 升序排列 */ //外層迴圈, 決定比較的輪次, 決定每輪需要確定的元素的下標 for (int i = 0; i < arr.length-1; i++) { //內層迴圈, 決定每輪比較時, 用於和i進行比較的下標的起止 for (int j = i+1; j < arr.length; j++) { //比較, 將較小的元素交換到下標i中 if(arr[i] > arr[j]) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } //輸出結果 System.out.println("排序後的陣列內容如下:"); for (int i = 0; i < arr.length; i++) { //輸出元素內容 System.out.print(arr[i] + "\t"); //判斷是否換行 if(i%5 == 4) { //(i+1)%5==0 System.out.println(); } } System.out.println("==========================================="); } }

四、插入排序

1、概念

將陣列劃分成兩個部分, 已經排序的部分, 和沒有排序的部分,依次從未排序的陣列中取出元素, 按照插入演算法, 插入已經排序的陣列部分,外層迴圈, 確定每次需要插入的元素的下標,記憶體迴圈, 遍歷已經排序的陣列的所有元素, 與需要插入的元素比較, 確定插入的具體效果

2、手寫程式碼

package com.array.sort;

/**
 * 插入排序
 * 基於插入演算法的排序
 * @author Administrator
 *
 */
public class Insertion {

	public static void main(String[] args) {
		
		//宣告陣列中
		int[] arr = new int[20];
		//遍歷陣列, 隨機生成元素內容
		for (int i = 0; i < arr.length; i++) {
			//生成1~100的隨機數
			arr[i] = (int) (Math.random()*100 + 1);
		}
		//輸出初始內容
		System.out.println("原陣列內容如下:");
		for (int i = 0; i < arr.length; i++) {
			
			//輸出元素內容
			System.out.print(arr[i] + "\t");
			
			//判斷是否換行
			if(i%5 == 4) { //(i+1)%5==0
				System.out.println();
			}
		}
		System.out.println("===========================================");
		
		/* 插入排序, 升序 */
		/*
		 * 將陣列劃分成兩個部分, 已經排序的部分, 和沒有排序的部分
		 * 依次從未排序的陣列中取出元素, 按照插入演算法, 插入已經排序的陣列部分 
		 */
		//外層迴圈, 確定每次需要插入的元素的下標
		for (int i = 1; i < arr.length; i++) {
			//記憶體迴圈, 遍歷已經排序的陣列的所有元素, 與需要插入的元素比較, 確定插入的具體效果
			for (int j = 0; j < i; j++) {
				
				//判斷, i下標的元素比j下標的元素小時, 交換
				if(arr[i] < arr[j]) {
					int temp = arr[i];
					arr[i] = arr[j];
					arr[j] = temp;
				}
			}
		}
		//輸出結果
		System.out.println("排序後的陣列內容如下:");
		for (int i = 0; i < arr.length; i++) {
			
			//輸出元素內容
			System.out.print(arr[i] + "\t");
			
			//判斷是否換行
			if(i%5 == 4) { //(i+1)%5==0
				System.out.println();
			}
		}
		System.out.println("===========================================");
	}
}

五、for、while、do-while區別

分四個方面:總的說、結構、特點、適用條件

1、總的來說,都是用來循壞的控制語句

2、do-while在while的括號後面加分號,而while迴圈的括號後不加分號

3、for和while是先進行迴圈條件判斷,再進入迴圈體,而do-while是先進入迴圈體,再執行迴圈條件,所以do-while至少出現一次。

4、適用條件:for適用於迴圈次數確定的情況

六、continue、break、return的異同

相同點

1、三個關鍵字都是用來終止迴圈的關鍵字,用了關鍵字會跳出相應的迴圈

不同點

2、continue是跳出當前迴圈進入下一個迴圈,break是退出迴圈,return是跳出方法,有返回值的話會返回要返回的值

七、==與equals方法的異同

相同:

都是用來進行比較操作

不同:

1、==是算術運算子,而equals是Object類的一個方法

2、基本資料型別的比較:只能用==運算子

3、非String類的引用資料型別,如果沒有重寫是Object類的equals方法,那麼兩者比較的都是物件的地址

4、String和重寫了equals方法的引用資料型別,==比較的還是地址,equals比較的就是值是否相等了。

八、談一談封裝

1、封裝的作用

封裝是面向物件三大特性之一,用封裝有利於保護資料的安全性

2、封裝的實現步驟

  • 私有化屬性private

    關於封裝時的屬性命名:首字母和第二個字母都不能大寫

  • get/set方法為屬性提供一個公開訪問的方法

  • 需要對相關屬性進行條件設定時,需要在set方法中進行設定

3、javabean

將欄位封裝成物件

九、談一談繼承

1、繼承的作用

繼承就是子類繼承父類的特徵和行為,是用extends關鍵字,使用繼承可以減少程式碼冗餘,提高類和類之間的耦合性

2、子類能從父類繼承到啥

廣義的說,子類能繼承到父類的除構造方法之外的所有,但是隻有父類的非私有子類才可以應用

3、java支援的是單根繼承,但是可以多重繼承

十、談一談多型

1、多型的作用

多型是同一個行為具有多個不同表現形式或形態的能力,消除型別之間的耦合性,增強程式碼的可替換性和可擴充套件性

2、實現多型的前提

  • 繼承和實現
  • 方法重寫(向上、向下轉型)

3、使用方式

  • 父類作為方法的形參傳遞
  • 父類作為方法返回值

十一、方法過載與方法重寫的異同

相同點:

1、方法名相同

2、兩者均提高了適用範圍和靈活性

不同點

1、出現的位置

重載出現在本類中,重寫出現在子類

2、參照的目標方法

過載參照的是同類的方法名相同的方法,重寫參照的是父類的方法

3、訪問修飾符

過載和訪問修飾符無關、重寫不能嚴於父類(比如父類用的是protected,那麼重寫的方法的訪問修飾符只能是protected活著public)

4、返回值型別

過載無關、重寫必須相同

5、引數列表型別或者數量

過載不同,重寫可完全一致或者是其子類型別

6、異常宣告

重寫不能丟擲比父類更多的異常,只能丟擲和父類型別一樣或是該異常的子類異常

十二、抽象類與介面的異同

相同點:

1、都不能被例項化,屬於抽象層面

2、都可以含有抽象方法

不同點:

1、關鍵字不同

抽象類:abstract,介面:interface

2、屬性要求不同

介面:public final static,初始值必須賦值,常量必須大寫

3、方法

抽象類可以有非抽象方法,介面方法只能是public abstract

4、構造方法

抽象類有構造方法,介面無

5、使用

抽象類單根繼承,介面多繼承多實現

十三、final、finally、finalize的區別

1、final

可修飾類、方法、屬性、區域性變數

修飾類不能被繼承,方法不能被重寫,屬性時一個常量在申明的時候必須賦值(因為全域性變數會有預設值),區域性變數可先申明再賦值)

2、finally

是異常處理時候的一個關鍵字,在try、catch和finally一起使用時,不管怎樣最後都會執行,除非呼叫System.exit(0)才不會執行

3、finalize

垃圾回收的時候使用

十四、在java中如何最有效率的將數值8變成2

使用位運算完成

左移<< 右移>> 按位與& 按位或| 按位亦或^ 按位非~

將資料轉換成2進位制後再處理. 32位2進位制數

4&5=4

4|5=5

100

101

100

先將8轉換為二進位制:1000,再將1000右移兩位變成10就是2,即8>>2

十五、this與super的異同

相同:

都是用來呼叫屬性和方法

不同:

1、呼叫 的類不同,this呼叫的是當前類,supper呼叫的是父類

2、this可以代表當前物件,supper無法代表父類

十六、談一談java的異常處理機制

1、什麼是程式錯誤

error:程式錯誤,如記憶體溢位

邏輯錯誤:和最後想要的的結果不同

Exception:程式異常

2、try、catch、finally

try是核心,代表對可能出現異常的程式碼塊進行異常捕捉,catch代表抓取異常,finally不管怎樣都會執行(除了一個)

3、有返回值return時

返回值是基本資料型別時:

最後返回的不會是finally的值

返回值是物件時:

最後返回的是finally的值

package com.param;

public class Test {

	public static void main(String[] args) {
		
		/*int n1 = 5,
			n2 = 10;
		cal(n1, n2);
		System.out.println(n1+","+n2);
		
		User user = new User("ÕÅÈý", 10);
		cal(user);
		System.out.println(user.getAge());*/
		
		/*int n = 10;
		System.out.println("n:" + n);
		System.out.println("result:" + cal(n));;*/
		
		User user = new User("º«Ã·Ã·", 20);
		System.out.println("result:" + cal(user));
	}
	
	private static User cal(User u) {
		
		try {
			
			u.setAge(100);
			System.out.println("try:" + u);
			return u;
		} catch (Exception e) {
			u.setAge(200);
			System.out.println("catch:" + u);
			return u;	
		} finally {
			u.setAge(1000);
			System.out.println("finally:" + u);
		}
	}
	
	private static int cal(int a) {
		
		try {
			a *= 10;
			System.out.println("try:" + a);
			int b = 1 / 0;
			return a;
		} catch (Exception e) {
			a += 100;
			System.out.println("catch:" + a);
			return a;
		} finally {
			a *= 1000;
			System.out.println("finally:" + a);
		}
	}
	
	private static void cal(int a, int b) {
		
//		System.out.println(a+b);
		a = 20;
		b = 50;
	}
	
	/*private static void cal(User u) {
		
//		u.setAge(50);
		
		u = new User("ÀîËÄ", 60);
		
	}*/
	
}

4、throws和throw

throws:丟擲異常,避免冗餘和重複工作

throws:申明異常,梳理結構

十七、談一談java的常見特性

1、面向物件

2、異常處理

3、垃圾回收

4、多執行緒

十八、ArrayList與LinkedList的異同

同:

都是屬於List介面的具體實現類,都實現了List中常用方法,並且都是有序不唯一的集合

不同:

1、各自的特點和使用場景

ArrayList遍歷效率高,對於只需要進行查詢操作的集合,用ArrayList集合儲存資料更好,因為ArrayList是連續的記憶體空間結構,所以查的快,但是插入刪除效率低;

LinkedList插入和刪除效率高,查詢效率低,因為LinkedList是鏈式儲存,每一個元素都含有三個元素,手拉手示的,插入塊

十九、ArrayList與Vector的區別

1、執行緒安全

Vector是同步的執行緒安全的,ArrayList執行緒不安全

2、執行效率

執行緒不安全的執行效率高

3、元素超過初始大小時

當Vector或ArrayList中的元素超過它的初始大小時,Vector會將它的容量翻倍,而ArrayList只增加50%的大小,這樣,ArrayList就有利於節約記憶體空間。

二十、HashMap與HashTable的區別

1、執行緒安全

HashMap執行緒不安全,HashTable執行緒安全

2、執行效率

執行緒不安全的執行效率高

二十一、String、StringBuffer、StringBiulder的異同

同:

都是用來儲存字串

不同:

1、從字串是否可變

String是不可變字串,後兩者均是可變 的

2、從執行緒安全形度

StringBiulder是安全的,其他都不安全

3、執行效率

StringBiulder比StringBuffer執行效率低

二十二、談一談反射

1、是什麼

反射是一種半動態的程式碼載入和執行機制,在jvm第一次載入位元組碼(.class)檔案時, 如發現了未知的未經編譯的資訊, 則會將未知資訊和位元組碼檔案返還給編譯器,由編譯器對未知資訊進行二次編譯,然後再交由jvm翻譯執行

2、比正常的編譯在JVM和編譯器間多了一個來回

3、獲取class類物件的方式:

​ 類名.class

​ 物件名.getClass

​ class.forName()字串

二十三、談一談序列化

1、作用

解決網際網路傳輸時,20%平均損失率問題,保證資料完整性

2、如何實現序列化

在實體類中實現serializable

,使用ObjectOutputStream

二十四、執行緒的生命週期

1、新生:new

2、可執行(就緒):start執行緒具有了搶奪資源的能力

3、執行:不穩定的狀態

4、阻塞:線城失去了搶奪資源的能力,sleep

5、死亡:

自然死亡:執行緒的run方法執行完

非自然死亡:容易死鎖

二十五、執行緒的排程

1、優先順序:setPriority

2、sleep(毫秒):

阻塞的是:呼叫該方法的執行緒

能否恢復可執行:能

3、join()

阻塞的是:別的執行緒,讓本執行緒先執行

能否恢復可執行:能

4、yield(),禮讓

阻塞的是:呼叫該方法的執行緒(時間極短,繼續槍佔資源)

能否恢復可執行:能

5、wait()

阻塞的是:自己

能否恢復可執行:不能,必須呼叫notify,兩者通常在兩個執行緒之間呼叫

二十六、程式併發的資料安全(執行緒鎖/執行緒安全)

1、多個使用者訪問同一資料時,會導致資料出現問題

2、執行緒同步方式

  • Synchronized同步方法
  • Synchronized同步程式碼塊
  • volatie關鍵字,申明域變數
  • 建立重入鎖物件重入鎖物件的操作方法: lock(), unlock()
  • 使用ThreadLocal宣告區域性變數

二十七、執行緒死鎖

  • 執行緒在執行過程中非正常死亡, 有機率導致死鎖
  • 2個執行緒在使用自己的資源的同時, 又去呼叫對方正在使用的資源

二十八、TCP

是一種面向連線的、可靠的、基於位元組流的傳輸層通訊協議,必須要求雙方建立連線後才開始通訊。

點對點傳輸,安全

伺服器端使用ServerSocket,使用其中的accept()方法監聽客戶端的請求,並使用Socket的getInputStream()和getOutputStream()方法,獲取伺服器端的輸出流和輸入流。

伺服器端使用Socket,並使用Socket的getInputStream()和getOutputStream()方法,獲取客戶端的輸出流和輸入流。

最後將相應的流和socket關閉即可

二十九、socket

基於TCP協議的資料中轉的物件,客戶端/伺服器

位於java.net包,被稱為套接字,是網路通訊連線的兩個端點,是網路驅動層提供給應用程式的一個介面或者一種機制。

三十、XML的常見解析方式

1、DOM解析

基於XML的樹結構來完成解析,通過獲取各個節點的元素物件,來獲取XML內容;

建立解析器工廠物件,獲得解析器物件,通過解析器物件對xml檔案解析獲得Document物件,Document物件的方法來獲取XML內容。

2、jDOM解析

JDOM是Java和DOM的結合體。利用純java技術對XML文件實現解析

3、SAX

基於事件解析,佔用資源小、記憶體消耗小

4、DOM4j

是一個開源的庫,特點是其中使用大量的介面,使用前需要匯入dom4j的jar包。獲得SAXReader物件,使用read()方法獲得Document物件,通過Document物件獲得根節點元素,來獲取XML的內容。

三十一、單例-懶漢

package com.singleton.lazy;

/**
 * 單例: 通過特殊的編碼格式,
 * 	保證該類的例項在一次程式執行過程中只有1個
 * 懶漢式
 * @author Administrator
 *
 */
public class Lazy {

	/* 1. 宣告私有的靜態屬性, 型別為本類型別 */
	private static Lazy lazy;
	
	/* 2. 隱藏構造方法 */
	private Lazy() {
	}
	
	/* 3. 提供一個公共的獲取類例項的靜態方法
		注: 此方法可以選擇同步或不同步.
	 */
	public synchronized static Lazy getInstance() {
		
		/* 4. 判斷, lazy屬性是否為null */
		if(lazy == null) {
			lazy = new Lazy();
		}
		
		return lazy;
	}
}

三十二、單例-餓漢

package com.singleton.hanger;

/**
 * 單例
 * 餓漢式
 * @author Administrator
 *
 */
public class Hanger {

	/* 1.宣告私有的靜態屬性, 型別為本類型別, 
	 * 並在宣告的同時例項化
	 */
	private static Hanger hanger = new Hanger();
	
	/* 2. 隱藏構造方法 */
	private Hanger() {
	}
	
	/* 3. 提供一個公共的獲取類例項的靜態方法
		注: 此方法可以選擇同步或不同步.
	 */
	public static Hanger getInstance() {
		return hanger;
	}
}

三十三、單例-雙重鎖

package com.singleton.dblock;

/**
 * 單例
 * 雙重鎖式
 * @author Administrator
 *
 */
public class DoubleLock {

	/* 1. 宣告私有的靜態屬性, 型別為本類型別
	 * 		並新增volatile關鍵字, 設定成域變數
	 *  */
	private volatile static DoubleLock doubleLock;
	
	/* 2. 隱藏構造方法 */
	private DoubleLock() {
	}
	
	/* 3. 提供一個公共的獲取類例項的靜態方法
	 */
	public static DoubleLock getInstance() {
	
		/* 4. 第一次判斷 */
		if(doubleLock == null) {
			/* 5. 同步程式碼塊, 並在程式碼塊中進行第二次判斷 */
			synchronized (DoubleLock.class) {
				if (doubleLock == null) {
					doubleLock = new DoubleLock();
				}
			}
		}
		
		return doubleLock;
	}
}

三十四、寫出5種java常見的設計模式(常規共23種)

1、單例模式。

單例模式對例項個數的控制並節約系統資源.

在它的核心結構中只包含一個被稱為單例類的特殊類,通過建構函式私有化和靜態塊以及提供對外訪問的介面來實現.

餓漢模式:單例例項在類的載入中就被建立.不需要判斷,安全.

private static MySingleton2 mySingleton = new MySingleton2(); 餓漢式 直接建立了物件

懶漢模式:單例例項在第一次使用時被建立.需要if判斷,不安全.

private static MySingleton2 mySingleton=null 懶漢式 靜態塊中會進行判斷

2、工廠模式

工廠模式主要是為建立物件提供了介面。

應用場景如下:

a、 在編碼時不能預見需要建立哪種類的例項。

b、 系統不應依賴於產品類例項如何被建立、組合和表達的細節

3、觀察者模式(一個學生對應多個老師,一個老師對應多個學生).

定義了物件間一對多的依賴關係,當一個物件改變狀態時,它的所有依賴者都會收到通知並自動更新。

應用場景如下:

a、對一個物件狀態的更新,需要其他物件同步更新,而且其他物件的數量動態可變。

b、物件僅需要將自己的更新通知給其他物件而不需要知道其他物件的細節。

4、迭代器模式。

迭代器模式提供一種方法順序訪問一個聚合物件中各個元素,而又不暴露該物件的內部表示。

應用場景如下:

當你需要訪問一個聚集物件,而且不管這些物件是什麼都需要遍歷的時候,就應該考慮用迭代器模式。其實stl容器就是很好的迭代器模式的例子。

5、代理模式

為其他物件提供代理來控制對該物件的訪問.

應用場景如下:

ngnix的反向代理(隱藏伺服器)運用的就是代理模式.

三十五、++和–

++和–都是java內部的算術運算子,但是在和其他運算子一起參與運算時,++放在前和放在後有順序問題

1、a++:參與運算的是沒有++之前的數字

++a:參與運算的是++之前的數字

Int a = 1;

實際改變的值 2 3 4

​ Int b = a++ * ++a * a++;

參與運算的值 1 3 3

經典面試題

int a = 0;
for(int i = 0; i < 6; i++){
實際:1
	a = a++;
運算:0
	System.out.print(a);  
}
輸出的是6個0,因為每一次參與運算的a都是0

三十六、&和&&

&&是短路與,兩個條件,如果前面那個為false,那麼直接整個結果就是false,不會走到第二個

&會走到第二個再判斷

經典面試案例

int	a1 = 7,
	a2 = 7,
	b1 = 8,
	b2 = 8;
boolean flag1 = a1++ > b1-- & a1++ > b1++;
boolean flag2 = a2++ > b2-- && a2++ > b2++;
a1, b1, a2, b2和flag1和flag2的值 
結果是:a1=9,b1=8,flag1=false
a2=8,b2=7,flag1=false

三十七、識別符號、變數

1、字母、下劃線、數字、$(64個)

2、數字不能放開頭

3、不能使用關鍵字

4、不能使用保留字goto、const

5、駝峰命名

6、見名知義

5.	long n = 324174641657646;——錯誤,要加L
float f = 5 / 2;
int n = ‘a’;
byte b = 127;
b++; b = b+ 1;

三十八、API

application programming interface
​ 應用程式編寫介面

三十九、java中48個關鍵字,和2個保留字

關鍵字:

abstract assert boolean break byte case
catch char class continue default do
double else enum extends final finally
float for if implements import int
interface instanceof long native new package
private protected public return short static
strictfp super switch synchronized this throw
throws transient try void volatile while

保留字:

goto const