昨天去了一家公司面試 Java 開發崗位,這篇文章主要是做一個面試的記錄以及總結。
這家公司的規模大概100-200人,環境還可以,在一棟大廈租了兩層辦公室(31層和32層)。一同搭電梯上去的還有一位去應聘測試崗位的妹紙🙂
這里要吐槽一下該公司的前台,由於跟HR約好了是在31樓面試,我和測試妹紙都去了31樓的前台,31樓的前台直接讓我們去樓上找32樓的前台,32樓的前台找了樓下31樓的面試官,結果又把我們帶回樓下31樓面試。
首先填了一份個人信息表,然后直接進入面試環節(沒有筆試 🙃)。
以下是面試時一些問題的記錄:
1、面向對象的三大特性
答:封裝、繼承、多態。
2、XML解析
答:
1、解析方式
- DOM:Document Object Model,文檔對象模型。這種方式是W3C推薦的處理XML的一種標准方式。
缺點:必須讀取整個XML文檔,才能構建DOM模型,如果XML文檔過大,造成資源的浪費。
優點:適合對XML中的數據進行操作(CRUD)。
- SAX:Simple API for XML。這種方式不是官方標准,屬於開源社區XML-DEV,幾乎所有的XML解析器都支持它。
2、解析工具
- JAXP:
DOM或SAX方式進行解析XML。API在JDK之中。
- Dom4J:(推薦)
是開源組織推出的解析開發包。(牛,大家都在用,包括SUN公司的一些技術的實現都在用)
3、反射
答:當我們的程序在運行時,需要動態的加載一些類,這些類可能之前用不到所以不用加載到jvm,而是在運行時根據需要才加載,這樣的好處對於服務器來說不言而喻。
舉個例子,我們的項目底層有時是用mysql,有時用oracle,需要動態地根據實際情況加載驅動類,這個時候反射就有用了,假設 com.java.dbtest.myqlConnection,com.java.dbtest.oracleConnection這兩個類我們要用,這時候我們的程序就寫得比較動態化,通過Class tc = Class.forName("com.java.dbtest.TestConnection");通過類的全類名讓jvm在服務器中找到並加載這個類,而如果是oracle則傳入的參數就變成另一個了。這時候就可以看到反射的好處了,這個動態性就體現出java的特性了!
舉多個例子,大家如果接觸過spring,會發現當你配置各種各樣的bean時,是以配置文件的形式配置的,你需要用到哪些bean就配哪些,spring容器就會根據你的需求去動態加載,你的程序就能健壯地運行。
4、Java 8 新特性
-
Lambda 表達式:Lambda允許把函數作為一個方法的參數(函數作為參數傳遞進方法中)。
-
方法引用:方法引用提供了非常有用的語法,可以直接引用Java的類方法、對象方法或者構造器。
5、Lambda 表達式
Lambda 表達式我們可以理解為對於函數式接口和其中的抽象方法的具體實現。
Lambda 表達式可以認為是一種特殊的匿名內部類,Lambda只能用於函數式接口。
lambda語法如下:
([形參列表,不帶數據類型]) -> {
//執行語句
[return..;]
}
代碼演示如下:
public class TestLambda {
public static void main(String[] args) {
TestLambdaInterface1 t1 = new TestLambdaInterface1() {
@Override
public void test() {
System.out.println("使用匿名內部類");
}
};
//與上面的匿名內部類執行效果一樣
//右邊的類型會自動根據左邊的類型進行判斷
TestLambdaInterface1 t2 = () -> {
System.out.println("使用lambda");
};
t1.test();
t2.test();
}
}
@FunctionalInterface
interface TestLambdaInterface1 {
//不帶參數的抽象方法
void test();
}
6、設計模式
單例模式
單例模式:確保一個類只有一個實例,並提供了一個全局訪問點。
實現:
-
使用一個私有靜態變量、一個私有構造函數以及一個公有靜態函數來實現。
-
私有構造函數保證了不能通過構造函數來創建對象實例,只能通過公有靜態函數返回唯一的私有靜態變量。
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
代理模式
發布訂閱模式
MVC 模式
7、Hibernate 的一級緩存、二級緩存
Session 的緩存被稱為 Hibernate 的第一級緩存。SessionFactory 的外置緩存稱為 Hibernate 的二級緩存。這兩個緩存都位於持久層,它們存放的都是數據庫數據的拷貝。SessionFactory 的 內置緩存 存放元數據和預定義 SQL,SessionFactory 的內置緩存是只讀緩存。
緩存的作用:
-
減少數據庫的訪問頻率,提高訪問性能。
-
保證緩存中的對象與數據庫同步,位於緩存中的對象稱為持久化對象。
8、ConcurrentHashMap 的 key 可不可以為 null ?
-
HashMap 可以允許插入 null key 和 null value
-
HashTable 和 ConcurrentHashMap 都不可以插入 null key 和 null value
9、線程池的線程命名
一、創建線程的時候沒有傳入名字
ThreadPoolManager.potatoPool.execute(new MyThread());
在這種情況下,線程池會給線程自動命名,如果想改變線程的名稱,那么需要在線程中的run方法中給線程setName。如下:
public class MyThread extends Thread{
public String threadName;
public MyThread (String threadName){
this.threadName=threadName;
}
@Override
public void run() {
Thread.currentThread().setName(threadName);
}
}
二、創建線程的時候直接傳入名字
ThreadPoolManager.potatoPool.execute(new MyThread("aa"));
10、Linux上安裝好MySQL,只能本機訪問,其他機器不能訪問的問題
1、權限問題,修改權限
2、防火牆的原因,修改防火牆配置
11、線程池核心線程數(core) 和 最大線程數(max)
當所有的核心線程(core) 都在干活時,新添加的任務會被添加到隊列中等待處理,如果隊列滿了,則新建非核心線程執行任務。
12、線程池捕獲異常
public class CaptureUncaughtException {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new ExceptionThread2()); // ExceptionThread2 為任務對象
}
}
/**
* MyUncaughtExceptionHandler:捕獲線程異常處理的類,需要實現 UncaughtExceptionHandler 接口
* @author nnngu
*/
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println(t+"捕獲到了異常,異常處理的對象為:"+e); // e:拋出的對象
}
}
13、Mybatis 的 Mapper
參考:
14、Jsp和servlet ,jsp的 9大內置對象
Servlet 的生命周期:init、service(doGet、doPost)、destory
JSP 的九大內置對象:
| 內置對象名 | 類型 |
|---|---|
| request | HttpServletRequest |
| response | HttpServletResponse |
| config | ServletConfig |
| application | ServletContext |
| session | HttpSession |
| exception | Throwable |
| page | Object(this) |
| out | JspWriter |
| pageContext | PageContext |
JSP 的四大域對象:
| 對象 | 域 |
|---|---|
| ServletContext | context域 |
| HttpServletRequet | request域 |
| HttpSession | session域 |
| PageContext | page域 |
15、文件上傳、socket、流
參考:
16、Netty
參考:
17、集合
答:List、Set、Map
List 是有序的,可以有重復元素
Set 是無序的,不允許有重復元素
Map 是鍵值對
18、IO 和 NIO
IO 和 NIO 的本質就是阻塞和非阻塞的區別。
阻塞概念:應用程序在獲取網絡數據的時候,如果網絡傳輸數據很慢,那么程序就一直等着,直到傳輸完畢為止。
非阻塞概念:應用程序直接可以獲取已經准備就緒的數據,無需等待。
參考:
Java NIO 系列教程
19、寫在最后
最后,我發現面試官也有一些錯誤,在此也把它記錄下來:
- 面試官說 NIO 是 JDK 1.5 之后引入的。(其實 NIO 是 JDK 1.4 開始引入的)
- 關於線程池的核心線程數(core) 和 最大線程數(max)的問題,面試官說當線程池里的線程數達到核心線程數(core) 時,新來了任務就會繼續創建線程來處理。(其實當線程數達到核心線程數之后,新來的任務會加入隊列等待處理,只有當隊列滿了才會繼續創建線程)
先寫到這里,以后有什么補充再更新。
