148道Java開發真實面試題及答案

1. Java的垮平臺原理

JVM也是一個軟件,不一樣的平臺有不一樣的版本。咱們編寫的Java源碼,編譯後會生成一種 .class 文件,稱爲字節碼文件。Java虛擬機就是負責將字節碼文件翻譯成特定平臺下的機器碼而後運行。也就是說,只要在不一樣平臺上安裝對應的JVM,就能夠運行字節碼文件,運行咱們編寫的Java程序。javascript

而這個過程當中,咱們編寫的Java程序沒有作任何改變,僅僅是經過JVM這一」中間層「,就能在不一樣平臺上運行,真正實現了」一次編譯,處處運行「的目的。css

JVM是一個」橋樑「,是一個」中間件「,是實現跨平臺的關鍵,Java代碼首先被編譯成字節碼文件,再由JVM將字節碼文件翻譯成機器語言,從而達到運行Java程序的目的。html

注意:編譯的結果不是生成機器碼,而是生成字節碼,字節碼不能直接運行,必須經過JVM翻譯成機器碼才能運行。不一樣平臺下編譯生成的字節碼是同樣的,可是由JVM翻譯成的機器碼卻不同。前端

因此,運行Java程序必須有JVM的支持,由於編譯的結果不是機器碼,必需要通過JVM的再次翻譯才能執行。即便你將Java程序打包成可執行文件(例如 .exe),仍然須要JVM的支持。java

注意:跨平臺的是Java程序,不是JVM。JVM是用C/C++開發的,是編譯後的機器碼,不能跨平臺,不一樣平臺下須要安裝不一樣版本的JVM。mysql

2. Java中INT佔幾個字節

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
char 佔2個字節
boolean 一個字節(1位)linux

3. Java面向對象的特徵

封裝、抽象、繼承和多態。nginx

封裝:在面嚮對象語言中,封裝特性是由類來體現的,咱們將現實生活中的一類實體定義成類,其中包括屬性和行爲(在Java中就是方法).例如電腦,程序員

抽象:抽象就是將一類實體的共同特性抽象出來,封裝在一個抽象類中,因此抽象在面嚮對象語言是由抽象類來體現的。好比人.
class Person{}web

繼承:繼承就像是咱們現實生活中的父子關係,兒子能夠遺傳父親的一些特性,在面嚮對象語言中,就是一個類能夠繼承另外一個類的一些特性,從而能夠代碼重用.
eg:class Zhangsan extends Person{};

多態:多態就是經過傳遞給父類對象引用不一樣的子類對象從而表現出不一樣的行爲
eg:Person person=new Zhangsan();

4. 裝箱和拆箱

裝箱就是自動將基本數據類型轉換爲包裝器類型;拆箱就是自動將包裝器類型轉換爲基本數據類型。

在這裏插入圖片描述

  1. Integer a = Integer.valueOf(123);//裝箱
  2. int b = a.intValue(); //拆箱

5. ==和EQUALS的區別

關於==
1.基本數據類型,也稱原始數據類型。byte,short,char,int,long,float,double,boolean 他們之間的比較,應用雙等號(),比較的是他們的值。
2.複合數據類型(類) 當他們用(
)進行比較的時候,比較的是他們在內存中的存放地

關於equals

Java 語言裏的 equals方法實際上是交給開發者去覆寫的,讓開發者本身去定義知足什麼條件的兩個Object是equal的。

6.String,StringBuilder,StringBuffer的區別

運行速度:StringBuilder >StringBuffer >String

String爲字符串常量,而StringBuilder和StringBuffer均爲字符串變量,即String對象一旦建立以後該對象是不可更改的,但後二者的對象是變量,是能夠更改的。Java中對String對象進行的操做其實是一個不斷建立新的對象而且將舊的對象回收的一個過程,因此執行速度很慢。而StringBuilder和StringBuffer的對象是變量,對變量進行操做就是直接對該對象進行更改,而不進行建立和回收的操做,因此速度要比String快不少。

線程安全:StringBuilder是線程不安全的,而StringBuffer是線程安全的

若是一個StringBuffer對象在字符串緩衝區被多個線程使用時,StringBuffer中不少方法能夠帶有synchronized關鍵字,因此能夠保證線程是安全的,但StringBuilder的方法則沒有該關鍵字,因此不能保證線程安全,有可能會出現一些錯誤的操做。因此若是要進行的操做是多線程的,那麼就要使用StringBuffer,可是在單線程的狀況下,仍是建議使用速度比較快的StringBuilder。

使用場景

String:適用於少許的字符串操做的狀況

StringBuilder:適用於單線程下在字符緩衝區進行大量操做的狀況

StringBuffer:適用多線程下在字符緩衝區進行大量操做的狀況

7. 講一下JAVA中的集合

java中的集合分爲value(Collection),和key-value(Map)兩種;

存儲value的有list和set兩種:
list是有序的,可重複的
set是無序的,不可重複的

存儲爲key-value是map:HashMap,Hashtable,CurrentHashMap

8. ARRAYLIST, Vector和LINKEDLIST的區別

  1. 區別

Vector、ArrayList都是以相似數組的形式存儲在內存中,LinkedList則以鏈表的形式進行存儲。
Vector線程同步,ArrayList、LinkedList線程不一樣步。
LinkedList適合指定位置插入、刪除操做,不適合查找;ArrayList、Vector適合查找,不適合指定位置的插入、刪除操做。
Vector默認擴充爲原來的兩倍,(每次擴充空間的大小是能夠設置的),而ArratList默認擴充爲原來的1.5倍(查看以前的文章),所以ArrayList更節省空間。

  1. 聯繫

ArrayList,Vector、LinkedList類均在java.util包中都是可改變大小的.
ArrayList和Vector都是基於存儲元素的Object[ ] array 來實現的,他們會在內存中開闢一塊連續的空間來存儲,因爲數據存儲是連續的,所以,他們支持用索引來訪問元素,同時索引數據的速度比較快。可是在插入元素時須要移動容器中的元素,因此對數據的插入操做執行的比較慢。ArrayList和Vector都有一個初始化的容量大小,當裏邊存儲的元素超過這個大小時就須要動態地擴充他們的存儲空間。

9. HASHMAP和HASHTABLE的區別

相同:HashMap和Hashtable均可以使用來存儲key-value的數據

區別:

基類不一樣:HashTable基於Dictionary類,而HashMap是基於AbstractMap。Dictionary是什麼?它是任何可將鍵映射到相應值的類的抽象父類,而AbstractMap是基於Map接口的骨幹實現,它以最大限度地減小實現此接口所需的工做。

線程安全:HashMap時單線程安全的,Hashtable是多線程安全的。

遍歷不一樣:HashMap僅支持Iterator的遍歷方式,Hashtable支持Iterator和Enumeration兩種遍歷方式。

null不一樣:HashMap能夠容許存在一個爲null的key和任意個爲null的value,可是HashTable中的key和value都不容許爲null。

多線程時,如何保障線程安全的同時也能保證效率?ConcurrentHashMap
經過把整個Map分爲N個segment(相似Hashtable),這樣既能夠保障線程安全,也能使效率提升N倍,默認是16倍.
ConcurrentHashMap當中每一個Segment各自持有一把鎖。在保證線程安全的同時下降了鎖的粒度,讓併發操做效率更高。

10. 實現一個拷貝文件的工具類要使用字節流仍是字符串

使用字節流,由於咱們要拷貝的文件,很差肯定裏面是否全是字符,若是文件中包含圖片之類的字節時,就須要使用字節流.因此,咱們通常是用字節流拷貝文件.

11. 線程的的實現方式?怎麼啓動線程?怎麼區分線程?

1.1.繼承Thread類,不推薦
1.2 實現Runnable 接口
1.3 實現java.util.concurrent下的Callable接口

12. 線程併發庫和線程池的做用

簡單瞭解過,JDK5中增長了併發庫,java.util.concurrent中提供了對線程優化.管理的各項操做,該包提供了線程的運行,線程池的建立,線程生命週期的控制.

線程池:java.util.concurrent.Executors建立四種線程池

newCachedThreadPool 建立非固定數量,可緩存的線程池,若線程池超過處理須要,可靈活回收空線程,若沒有線程可回收,則建新線程
newFixedThreadPool固定線程池,底層是無界隊列,可控制最大併發數,超出的線程會在隊列中等待
newScheduledThreadPool定時執行線程池,支持定時及週期性任務執行
newSingleThreadExecutor單線程化的線程池,只會用惟一的工做線程來執行任務,保證全部任務按照順序執行
線程池的好處:

限定線程的個數,不會致使因爲線程過多致使系統運行緩慢或崩潰
線程池每次都不須要去建立和銷燬,節約了資源
線程池不須要每次都去建立,相應時間更快.

13. 設計模式和經常使用的設計模式(選擇本身熟悉的說,最好能手寫)

設計過程當中能夠反覆使用的、能夠解決特定問題的通用模板。

建立型模式(5種):工廠方法模式,抽象工廠模式,單例模式,建造者模式,原型模式。
結構型模式(7種):適配器模式,裝飾器模式,代理模式,外觀模式,橋接模式,組合模式,享元模式。
行爲型模式(11種):策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

14. HTTP GET POST請求的區別

一、GET請求,請求的數據會附加在URL以後,以?分割URL和傳輸數據,多個參數用&鏈接。URL的編碼格式採用的是ASCII編碼,而不是uniclde,便是說全部的非ASCII字符都要編碼以後再傳輸。

POST請求:POST請求會把請求的數據放置在HTTP請求包的包體中。

所以,GET請求的數據會暴露在地址欄中,而POST請求則不會。

二、傳輸數據的大小

在HTTP規範中,沒有對URL的長度和傳輸的數據大小進行限制。可是在實際開發過程當中,對於GET,特定的瀏覽器和服務器對URL的長度有限制。所以,在使用GET請求時,傳輸數據會受到URL長度的限制。

對於POST,因爲不是URL傳值,理論上是不會受限制的,可是實際上各個服務器會規定對POST提交數據大小進行限制,Apache、IIS都有各自的配置。

三、安全性

POST的安全性比GET的高。這裏的安全是指真正的安全,而不一樣於上面GET提到的安全方法中的安全,上面提到的安全僅僅是不修改服務器的數據。好比,在進行登陸操做,經過GET請求,用戶名和密碼都會暴露再URL上,由於登陸頁面有可能被瀏覽器緩存以及其餘人查看瀏覽器的歷史記錄的緣由,此時的用戶名和密碼就很容易被他人拿到了。

15. 說說你對SERVLET的理解

就是一個運行在WEB服務器上的小的Java程序,用來接收和響應從客戶端發送過來的請求,一般使用HTTP協議.

使用:

一、編寫一個Java類,實現servlet接口。

二、把開發好的Java類部署到web服務器中。

按照一種約定俗成的稱呼習慣,一般咱們也把實現了servlet接口的java程序,稱之爲Servlet

Servlet            :接口
    |
 GenericServlet :通用的Servlet
    |
 HttpServlet        :HttpServlet

編寫一個類繼承HttpServlet,重寫doGet和doPost方法.

  • 配置
  • 在這裏插入圖片描述

16. SERVLET的生命週期

用戶第一次訪問Servlet的時候,服務器會建立一個Servlet的實例,那麼Servlet中init方法就會執行.任何一次請求服務器都會建立一個新的線程訪問Servlet中的service的方法.在service方法內部根據請求的方式的不一樣調用doXXX的方法.(get請求調用doGet,post請求調用doPost).當Servlet中服務器中移除掉,或者關閉服務器,Servlet的實例就會被銷燬,那麼destroy方法就會執行.

17. SERVLET中FORWARD和REDIRECT的區別

重定向(redirect)實際上是兩次request,第一次,客戶端request,A服務器響應,並response回來,告訴瀏覽器,你應該去B。這個時候IE能夠看到地址變了,並且歷史的回退按鈕也亮了。重定向能夠訪問本身web應用之外的資源。在重定向的過程當中,傳輸的信息會被丟失。
請求轉發(forward)是服務器內部把對一個request/response的處理權,移交給另一個.對於客戶端而言,它只知道本身最先請求的那個A,而不知道中間的B,甚至C、D。傳輸的信息不會丟失。

18. JSP和SERVLET的相同點和不一樣點

聯繫:
JSP 是 Servlet 技術的擴展,本質上是 Servlet 的簡易方式,更強調應用的外表表達。
JSP編譯後是」類 servlet」。
不一樣點:

  • Servlet 的應用邏輯是在Java文件中,而且徹底從表示層中的HTML裏分離開來。Servlet若是要實現html功能,必須使用Writer輸出對應的html.
  • JSP 的狀況是Java和HTML能夠組合成一個擴展名爲.jsp 的文件。作界面展現比較方便,而嵌入邏輯複雜.
  • JSP 側重於視圖,Servlet 主要用於控制邏輯

19. jsp內置對象和四大做用域和頁面傳值

內置對象名 類型
request HttpServletRequest
response HttpServletResponse
config ServletConfig
application ServletContext
session HttpSession
exception Throwable
page Object(this)
out JspWriter
pageContext PageContext
域 範圍
page域 只能在當前jsp頁面使用
request域 只能在同一個請求中使用
session域 只能在同一個會話(session對象)中使用
context域 只能在同一個web應用中使用

20. SESSION和COOKIE的區別和使用場景

Session和cookie都是會話(session)跟蹤技術.cookie經過在客戶端記錄信息肯定用戶身份,而session是經過在服務器端記錄信息肯定用戶身份.可是session的實現依賴於cookie機制來保存JESESSIONID(session的惟一標識,須要存在客戶端)

區別:

cookie的數據存儲在客戶端,session的數據存儲在服務器上
cookie不是很安全,別人能夠經過分析存放在本地的cookie並進行cookie欺騙,考慮到安全應該使用session
session會在必定時間內保存在服務器上,當訪問增多時,會影響服務器的性能.考慮到服務器性能,應當使用cookie.
單個cookie保存數據不能超過4k,不少瀏覽器顯示一個站點最多保存20個cookie
將重要信息保存在session中(登錄),將其餘須要保留的信心存放在cookie中(購物車,cookie是能夠在客戶端禁用的,這時候要使用cookie+數據庫的方式實現購物車,當cookie中不能取出數據,就從數據庫中取)

21. MVC模式和MVC各部分的實現

MVC的全名是Model View Controller,是模型(model)-視圖(view)-控制器(controller)的縮寫,是一種軟件設計典範.低耦合(m和v的分離)
struts2的mvc:jsp–>StrutsPrepareAndExecuteFilter(前端控制器,核心控制器)+action–>javabean–>result

22. 數據庫分類和經常使用數據庫

  • 關係型:MySQL、 ORACLE、SQL Server、IBM DB二、Sybase
  • 非關係型:Redis,Memcached,MongoDB ,Hadoop

23. 關係型數據庫的三範式

範式就是規範,就是關係型數據庫設計表時遵循的三個規範.要知足第二範式,必須先知足第一範式,要知足第三範式,必須先知足第二範式

1.第一範式(1NF)是指數據庫表的每一列都是不可分割的基本數據項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。列數據的不可分割.
2.第二範式(2NF)要求數據庫表中的每一個實例或行必須能夠被惟一地區分。爲實現區分一般須要爲表加上一個列,以存儲各個實例的惟一標識.(主鍵)
3.第三範式(3NF)要求一個數據庫表中不包含已在其它表中已包含的非主關鍵字信息。(外鍵)

反三範式:有時候爲了效率,能夠設置重複或者可推導出的字段.好比:訂單(總價),訂單項(單價)

24. 事務的四大特徵

事務是併發控制的單位,是用戶定義的一個操做序列.這些操做要麼都作,要麼都不作,是一個不可分割的工做單位.例子:轉帳

事務的四大特性:ACID

1.原子性(Atomicity):表示事務內不可分割,要麼都成功,要麼都失敗
2.一致性(Consistency):要麼都成功,要麼都失敗.失敗了,要對前面的操做進行回滾
3.隔離性(Isolation):一個事務開啓了,不能受其它事務的影響
4.持久性(Durability):持續性,表示事務開始了,就不能終止.事務提交後,將數據序列化到數據庫

25. MYSQL數據庫最大鏈接數

數據庫默認的最大鏈接數是100,在實際操做中,咱們會去修改這個值:mysql安裝文件–>my.ini文件

# The maximum amount of concurrent sessions the MySQL server will
# allow. One of these connections will be reserved for a user with
# SUPER privileges to allow the administrator to login even if the
# connection limit has been reached.
max_connections=100

26. MYSQL和ORACLE的分頁語句

爲何要分頁?不少數據不能徹底展現出來,須要進行分段顯示

mysql:是使用關鍵字limit來進行分頁的.LIMIT [offset,] rows:offset指定要返回的第一行的偏移量(也就是從哪一個索引開始),rows第二個指定返回行的最大數目。初始行的偏移量是0(不是1)
oracle:通常是使用rownum 加select 嵌套查詢

27. 觸發器的使用場景

觸發器:觸發器須要有觸發條件,當條件知足後,作什麼操做

應用場景:某些社交軟件的日誌更新,會通知好友; 一些論壇中,當插入新帖時,會更改當前帖子總數以及最後發帖時間.

CREATE [or REPLACE] TRIGGER 觸發器名
BEFORE | AFTER
[DELETE ][[or] INSERT] [[or]UPDATE [OF 列名]]
ON 表名
[FOR EACH ROW ][WHEN(條件) ]
declare
……
begin
PLSQL 塊
End ;

28. 存儲過程的優勢

1.存儲過程只在建立時進行編譯,之後每次執行它都不會再從新編譯.通常SQL語句每次執行都會編譯.因此存儲過程會大大提升數據庫執行速度
2.一般複雜的業務邏輯須要多條SQL語句,這些語句要分別從客戶機發送到服務器,當客戶機和服務器之間的操做不少時,會產生大量的網絡傳輸.若是將這些操做放在一個3.存儲過程當中,那麼客戶機和服務器之間的網絡傳輸會大大減小,下降網絡負載.
4.存儲過程是可重複使用的,能減小數據庫開發人員的工做量.
5.存儲過程能夠屏蔽對底層數據對象的直接訪問,使用EXECUTE權限調用存儲過程,無需擁有訪問底層數據庫對象的顯示權限,安全性高.

29. JDBC調用存儲過程

加載驅
獲取鏈接
設置參數
執行
釋放鏈接

30. 簡單說一下你對JDBC的理解

Java database connection java數據庫鏈接,數據庫關係系統不少,每一個數據庫關係管理系統支持的命令是不同的.
Java只定義接口,讓數據庫廠商本身實現接口,對於咱們開發人員而言,只須要導入對應廠商開發的實現便可,而後以接口的方式進行調用(mysql+mysql驅動(實現)+jdbc)

31. 寫一個JDBC的訪問ORACLE的列子

public class OracleUtils {
static {
    try {
        Class.forName("oracle.jdbc.driver.OracleDriver");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
 
//獲取鏈接
public static Connection getConnection() throws SQLException {                                                  
    Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@ip:1521:orcl", "username", "password");
    return conn;
 
}
//關閉資源
public static void close(ResultSet rs, Statement stmt, Connection conn) {
}
}
.....
調用
Connection conn = OracleUtils.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
OracleUtils.close(rs, stmt, conn);

32. JDBC中PREPAREDSTATEMENT比STATEMENT的好處

PreparedStatement能夠防止sql注入攻擊,它是預編譯的,

33. 數據庫鏈接池的做用

限定數據庫的鏈接個數,不會因爲數據庫鏈接過多致使系統運行緩慢或崩潰
數據庫鏈接不須要每次都去建立或銷燬,節約了資源
數據庫鏈接不須要每次都去建立,響應時間更快.

34. 簡單說一下HTML,CSS,JAVASCRIPT在網頁開發中的定位

Html 超文本標記語言,定義網頁的結構
Css 層疊樣式表,用來美化頁面
Javascript 主要用來驗證表單,作動態交互(其中ajax)

35. 簡單介紹了一下AJAX

什麼是ajax?異步的javascript和xml
做用是什麼?經過ajax與服務器進行數據交換,ajax能夠使網頁實現局部更新.這意味着能夠在不從新加載整個網頁的狀況下,對網頁的某部分進行更新.
怎麼實現?ajax xmlhttpRrqueset對象,使用這個對象能夠異步向服務器發送請求,獲取響應,完成局部更新,open send responseText/responseXml局部響應.
使用場景:登錄失敗時不跳轉頁面,註冊時提示用戶名是否存在,二級聯動等等.

36. JS和JQUERY的關係

JQuery是一個js框架,封裝了js的屬性和方法,而且加強了js的功能,讓用戶使用起來更加便利,而且加強了js的功能.
原來是使用js是要處理不少兼容性的問題(好比註冊事件等),由JQuery封裝了底層,就不用處理兼容性問題.
原生的js的dom和事件綁定和ajax等操做很是麻煩,JQuery封裝了之後,操做很是方便.

37. JQUERY中的經常使用選擇器

ID選擇器
Class選擇器
標籤選擇器
通用選擇器
層次選擇器
屬性選擇器

38. JQUERY中頁面加載完畢事件

爲何須要頁面加載事件?不少時候咱們須要獲取元素,可是必須等到該元素被加載後才能獲取,咱們能夠把js代碼放到該元素的後面,可是這樣就會形成js在咱們的body中存在很差管理.全部頁面加載完畢後,全部的元素固然已經加載完畢,通常獲取元素作操做都要在頁面加載完畢後.
$(function{}表示的是頁面結構被加載完畢
Window.onload表示的是頁面被加載完畢

39. JQUERY中AJAX和原生JS實現AJAX的關係

JQuery中的ajax也是經過原生的js封裝的,封裝完成後讓咱們使用起來更加便利,不用考慮底層實現或兼容性等的處理.
若是採用原生js實現ajax是很是麻煩的,而且每次都是同樣的.若是咱們不適用JQuery,咱們也要封裝對象的方法和屬性,有像JQuery這些已經封裝完成,通過不少企業實踐過的框架,比較可靠,咱們不須要封裝,直接使用成熟的框架(JQuery)便可.

40. BOOTSTRAP的是什麼

Bootstrap是一個移動設備優先的UI框架.咱們不用寫任何的css和js代碼就能實現比較漂亮的有交互性的頁面.咱們程序員對頁面的編寫是有硬傷的,因此要本身寫頁面的話,就要使用相似bootstrap這樣的UI框架.
平時常常用的:
模態框
表單,表單項
佈局
柵格系統

41. 什麼是框架

框架(Framework)是一個框子—–具備約束性,也是一個架子—-具備支撐性.
IT語境中的框架,特支爲解決一個開放性問題而設計的具備必定約束性的支撐架構.在此結構上能夠根據具體問題擴展.安插更多的組成部分.從而更迅速和更方便的構建完整的解決問題的方案.

框架自己通常不完整到能夠解決特定問題,可是能夠幫助咱們快速解決特定問題
框架天生就是爲了擴展而設計的
框架裏面能夠爲後續擴展的組件提供不少輔助性,支撐性的方便易用的使用工具.也就是說框架時常配套; 一些幫助解決某類問題的庫或工具.

42. 簡單介紹一下MVC模式

MVC全名是model view Controller,是模型(model)—視圖(view)—控制器(Controller)的縮寫,是一種軟件設計典範.
最簡單的,最經典的就是jsp(view)+servlet(Controller)+javabean(model)
1.當控制器收到來自用戶的請求
2.控制器調用javabean完成業務
3.完成業務後經過控制器跳轉jsp頁面的方式給用戶反饋信息
4.Jsp給用戶作出響應

43. 簡單說一下對MVC框架的理解

是爲了解決傳統的MVC模式(jsp+servlet+javabean)問題而出現的框架.

傳統MVC模式問題
1.全部的servlet和servlet映射都要配置在web.xml中,若是項目太大,web.xml就太龐大,而且不能實現模塊化管理.
2.Servlet的主要功能就是接受參數,調用邏輯,跳轉頁面,好比像其餘字符編碼,文件上傳等功能也要寫在servlet中,不能讓servlet功能單一.
3.接受參數比較麻煩,不能經過model接收,只能單個接收,接收完成後轉換封裝進model.
4.跳轉頁面方式比較單一(forward,redirect),而且當頁面名稱發生變化時,須要修改servlet源代碼.

經常使用的MVC框架:struts2,springMVC

44. STRUTS2的執行流程或者STRUTS2的原理

1.瀏覽器發送請求,通過一系列的過filter,到達strutsPrepareAndExecuteFilter
2.strutsPrepareAndExecuteFilter經過ActionMapper判斷當前的請求是否須要某個Action處理,若是不須要,則走原來的流程.若是須要,把請求交個ActionProxy來處理
3.ActionProxy經過Configuration Manager 詢問框架的配置文件struts.xml,找到須要調用的Action類;
4.建立一個ActionInvocation實例,來調用Action的對應方法來獲取結果集的name,在調用先後會執行相關攔截器
5/經過結果集的name找到對應的結果集來對瀏覽器進行響應

45. STRUTS2的攔截器是什麼

經過動態配置方式,能夠在執行Action的方法先後,加入相關邏輯,完成業務 .struts2中的功能, 都是經過系統攔截器實現的.好比:參數處理,文件上傳,字符編碼.固然,咱們也能夠自定義攔截器
使用場景:用戶登錄判斷,在執行Action的前面判斷是否已經登錄,若是沒有登錄則跳轉到登錄頁面;用戶權限的判斷,在執行Action的前面判斷是否具備權限,若是沒有給出提示信息;

46. SPRING MVC的執行流程

1.用戶發送請求,被前端控制器(DispatcherServlet)捕獲(捕獲請求)
2.前端控制器進行解析,獲得URI,經過URI調用HandlerMapping並得到該Handler配置的全部相關對象(查找Handler)
3.前端控制器根據獲得的Handler,選擇合適的HandlerAdapter,提取Request中的模型數據,填入Handler入參,開始執行Handler,最後返回一個ModelAndView對象.(執行Handler)
4.前端控制器根據返回的ModelAndViewm,選擇合適的ViewResolver(選擇ViewResolver)
5.經過ViewResolver結合Model和View來渲染視圖,前端控制器將渲染結果返回給客戶端(渲染並返回)

47. SPRINGMVC和STRUTS2的不一樣

核心控制器不一樣:springmvc是servlet,struts2是filter
控制器實例:springmvc會比struts快(理論上),springmvc是基於方法設計,struts是基於對象,每發一次請求都會實例一個action.springmvc只有一個實例,每次請求執行對應的方法便可,簡單來講,springmvc是單例,是trust是多例
管理方式:springmvc是spring的一個模塊,因此spring對於springmvc的控制管理更加簡單方便.而struts須要使用xml配置不少參數來管理
參數傳遞:struts2中自身提供多種參數接收,其實都是經過valuestack進行傳遞和賦值.而springmvc是經過方法參數進行接收.
interceptor的實現機制:struts有本身的interceptor機制,springmvc用的是獨立的aop方式.
Springmvc處理ajax請求,直接返回數據,方法中使用註解@ResponseBody,springmvc自動幫咱們將數據轉成json數據,而struts2是經過插件的方式進行處理

48. 簡單介紹一下SPRING或者SPRING的兩大核心

Spring是什麼?spring是j2ee應用程序框架,是輕量級的IOC和AOP的容器框架,主要針對javabean的生命週期進行管理的輕量級容器,能夠單獨使用,也能夠跟其它框架組合使用.

IOC(inversion of control)或DI(dependency injection)控制反轉

原來:個人service要調用Dao,我就在service中建立Dao對象,這時Dao對象的建立的控制權在我手中

Spring:spring發現個人service依賴於Dao,就給個人service注入Dao對象,這時Dao對象建立的控制權在spring手中

核心原理:工廠模式+反射+配置文件

AOP:面向切面編程

核心原理:使用動態代理的方式在執行先後或出現異常後作相關邏輯.

咱們主要使用AOP來作:

事務處理

權限判斷

日誌記錄

49. AOP是什麼?都用它作什麼

AOP:面向切面編程
核心原理:使用動態代理的方式在執行先後或出現異常後作加入相關邏輯.
咱們主要使用AOP來作:
事務處理 執行方法前,開啓事務,執行方法後提交事務,出現異常後回滾事務
權限判斷 在執行方法前,判斷是否具備權限
日誌記錄 在執行方法前執行日誌

50. SPRING事務的傳播特性和隔離級別

事務的傳播特性:多個事務存在是怎麼處理的策略.

傳播行爲 意義
PROPAGATION_MANDATORY 表示該方法必須運行在一個事務中。若是當前沒有事務正在發生,將拋出一個異常
PROPAGATION_NESTED 表示若是當前正有一個事務在進行中,則該方法應當運行在一個嵌套式事務中。被嵌套的事務能夠獨立於封裝事務進行提交或回滾。若是封裝事務不存在,行爲就像PROPAGATION_REQUIRES同樣。
PROPAGATION_NEVER 表示當前的方法不該該在一個事務中運行。若是一個事務正在進行,則會拋出一個異常。
PROPAGATION_NOT_SUPPORTED 表示該方法不該該在一個事務中運行。若是一個現有事務正在進行中,它將在該方法的運行期間被掛起。
PROPAGATION_SUPPORTS 表示當前方法不須要事務性上下文,可是若是有一個事務已經在運行的話,它也能夠在這個事務裏運行。
PROPAGATION_REQUIRES_NEW 表示當前方法必須在它本身的事務裏運行。一個新的事務將被啓動,並且若是有一個現有事務在運行的話,則將在這個方法運行期間被掛起。
PROPAGATION_REQUIRES 表示當前方法必須在一個事務中運行。若是一個現有事務正在進行中,該方法將在那個事務中運行,不然就要開始一個新事務。

ISOLATION_DEFAULT 使用後端數據庫默認的隔離級別。
ISOLATION_READ_UNCOMMITTED 容許讀取還沒有提交的更改。可能致使髒讀、幻影讀或不可重複讀。
SOLATION_READ_COMMITTED 容許從已經提交的併發事務讀取。可防止髒讀,但幻影讀和不可重複讀仍可能會發生。
ISOLATION_REPEATABLE_READ 對相同字段的屢次讀取的結果是一致的,除非數據被當前事務自己改變。可防止髒讀和不可重複讀,但幻影讀仍可能發生。
ISOLATION_SERIALIZABLE 徹底服從ACID的隔離級別,確保不發生髒讀、不可重複讀和幻影讀。這在全部隔離級別中也是最慢的,由於它一般是經過徹底鎖定當前事務所涉及的數據表來完成的。

51. ORM是什麼?ORM框架是什麼?

對象關係映射(Object Relational Mapping,簡稱ORM)模式是一種爲了解決面向對象與關係數據庫存在的互不匹配的現象的技術。簡單來講,將程序中的兌現自動持久化到關係數據庫中。那麼,到底如何實現持久化呢?一種簡單的反感是採用硬編碼的方式(jdbc操做sql方式),爲每一種可能的數據庫訪問操做提供單獨的方法。這種方法存在不少缺陷,因此使用ORM框架(爲了解決面型對象與關係數據庫存在的互不匹配的現象的框架)來解決。

Java典型的ORM框架有:Hibernate,mybatits

52. WEBSERVICE的使用場景

Webservice是一個SOA(面向服務的編程)的架構,它是不依賴於語言,不依賴於平臺,能夠實現不一樣的語言間的相互調用,經過Internet進行基於http協議的網絡應用間的交互.

異構系統(語言)的整合
不一樣客戶端的整合,瀏覽器 手機端 pc端等終端的訪問
例子:
天氣預報:能夠經過實現webservice客戶端調用遠程天氣服務實現的.
單點登陸:一個服務器實現全部系統的登錄

53. ACTIVITI的簡單介紹

Activiti是一個業務流程管理(BPM)和工做流系統,適用於開發人員和系統管理人員,其核心是超快速,穩定的BPMN2流程引擎,它易與spring集成使用.
主要用在OA中,把線下流程放到線上,把現實生活中的一些流程固話定義到系統中,而後經過輸入表單數據完成業務.

54. LINUX的使用場景

Linux是一個長時間運行比較穩定的操做系統,因此咱們通常會拿它做爲服務器(web,db.app等).
Linux自己具備c的編譯環境.咱們的一些軟件是沒有軟件包的(redis,nginx),須要在linux編譯獲得軟件包

55. LINUX經常使用命令

Cd跳轉到目錄
Pwd 獲取當前路徑
Su 切換用戶
Ll 查看當前目錄下文件和目錄
Tail 查看文件
Rm –rf 刪除文件
Vi 修改文件
Mv 移動/重命名 文件或文件夾
Mkdir 建立文件夾
Rm –f 刪除文件夾
Tar 打包/解壓
Grep 查找想要的信息

56. 怎麼操做LINUX服務器

須要依賴於linux服務器安裝ssh服務端,通常這個ssh服務的端口爲22,
須要依賴於linux服務器安裝sftp服務端,通常這個sftp服務的端口爲25,

使用ssh客戶端鏈接linux服務器,經過命令操做linux服務器
使用sftp客戶端來鏈接sftp服務端,來上傳和下載文件(安裝包,修改文件上傳)

57. 有沒有使用過雲主機

使用過阿里雲
雲主機:就是一些雲服務運營商(阿里,華爲,新浪等)提供的遠程服務器功能,咱們公司只要付費就能夠租用對應的服務器.

58. 數據庫優化方面的事情

定位:查找,定位慢查詢,並優化
優化
1.建立索引:建立合適的索引,咱們就能夠在索引中查詢,查詢到之後直接找對應的額記錄
2,分表:當一張表的數據比較多或者一張表的某些字段的值比較多而且不多使用時,採用水平分表或垂直分表來優化,好比spu表
3,讀寫分離:當一臺服務器不能知足須要時,採用將讀寫分離的方式進行集羣
4.緩存:使用redis來進行緩存

59. 選擇合適的索引

索引是幫助DBMS高效獲取數據的數據結構.
分類:普通索引,惟一索引,主鍵索引,全文索引
1.普通索引:容許重複的值出現
2.惟一索引:除了不能有重複的記錄外,其它和普通索引同樣.(用戶名;用戶身份證;手機號)
3.主鍵索引:是隨着設定主鍵而建立的;也就是把某個列設爲主鍵的時候,數據庫就會給該列建立索引;惟一且沒有null值
4.全文索引:用來對錶中文本域(char,varchar,text)進行索引,全文索引針對myisam

60. 使用索引的一些技巧

索引弊端:

  1. 佔用磁盤空間.
  2. 對dml(插入,修改.刪除)操做有影響,變慢
    使用場景:
  3. 確定在where條件常用,若是不作查詢就沒有意義
  4. 該字段的內容不是惟一的幾個值(sex).
  5. 字段內容不是頻繁變化

61. 項目的併發

1.需求:用戶量,這個客戶說了算,大概也就是1-5年內用戶總量
2.根據pv(頁面點擊量,瀏覽量)和uv(ip數量)預估,大體能達到多大的併發量.咱們的項目大概能達到1000-3000的併發量
3.肯定咱們的服務器數量,咱們使用的是tomcat,tomcat的默認線程數150,咱們能夠將它優化調到400左右.而咱們大體須要5臺web服務器
4.重要的因素(硬件服務器水平—去IOE),咱們沒有作這個,由於咱們沒錢.

62. http協議

1.無狀態,爲了解決http無狀態問題,引入cookie技術
2.http1.0是短鏈接,http1.1是長鏈接
3.http協議是基於B/S請求-應答模式

63. cookie和session

1.Cookie是由服務器建立的,經過response對象的addCookie(Cookie cookie)方法寫回客戶端,存儲在客戶端的會話技術.key-value的結構
2.session是基於cookie,session的建立是由服務器作,能夠經過request.getSession()獲取(要從你的請求中找一個cookie—Jessionid,若是能找到這個cookie,他會拿着這個cookie的值去跟服務器端的session的id比較,若是找到相應的session,就不建立session.若是找不到相應的session,會建立session).session一旦建立就會有一個id屬性(惟一的),經過response以cookie的方式寫回客戶端(這個cookie就叫作就sessionid).

會話:會話就是簡單的理解成打開瀏覽器(包含了一次請求或屢次請求).

64. session共享的方案

1.廣播:會形成內網網絡風暴,大量佔用內網寬帶
2.IP_hash:在nginx中配置和,相同的ip找固定的同一臺服務器,這種方案會形成服務能力差
3.使用第三方中間件(數據庫,redis),咱們是使用redis

65. 高併發問題:索引庫同步

1.硬編碼:在相應的代碼中增長索引庫同步的代碼。不過,這種方法耦合度過高,將本來不相關的系統耦合在了一塊兒,容易形成不可預估的錯誤,是電商項目的大忌。
2.spring的aop:編寫一個索引庫同步的方法,利用aop的形式,將它和數據庫數據更新的方法聯繫起來。這種方式也會形成耦合。
3.消息隊列:不過,這個方法會形成一個問題,那就是消息消費失敗問題。

66. 單點登陸的核心是什麼

單點登陸的核心是如何在多個系統之間共享身份信息

67. solr 的索引查詢爲何比數據庫要快

Solr 使用的是 Lucene API 實現的全文檢索。全文檢索本質上是查詢的索引。而數據庫中並
不是全部的字段都創建的索引,更況且若是使用 like 查詢時很大的多是不使用索引,因此
使用 solr 查詢時要比查數據庫快。

68. solr 索引庫個別數據索引丟失怎麼辦

首先 Solr 是不會丟失個別數據的。若是索引庫中缺乏數據,那就向索引庫中添加

69. IO和NIO

IO NIO
面向流 面向緩衝
阻塞IO 非阻塞IO
無 選擇器

70.https和http

HTTP:是互聯網上應用最爲普遍的一種網絡協議,是一個客戶端和服務器端請求和應答的標準(TCP),用於從WWW服務器傳輸超文本到本地瀏覽器的傳輸協議,它能夠使瀏覽器更加高效,使網絡傳輸減小。
HTTPS:是以安全爲目標的HTTP通道,簡單講是HTTP的安全版,即HTTP下加入SSL層,HTTPS的安全基礎是SSL,所以加密的詳細內容就須要SSL。
HTTPS協議的主要做用能夠分爲兩種:一種是創建一個信息安全通道,來保證數據傳輸的安全;另外一種就是確認網站的真實性。

71.TCP和UDP的區別

1.tcp面向鏈接(如打電話要先撥號鏈接);udp是無鏈接的,即發送數據以前不須要鏈接
2.tcp提供可靠的服務。也就是說經過tcp傳送的數據,無差錯,無丟失,不重複,且按序到達;udp盡最大努力交付,不保證交付是否成功
3.tcp面下字節流,實際上tcp把數據當作是一連串無結構的字節流;udp是面向報文的,udp沒有擁塞控制,所以網絡出現擁塞不會使源主機的發送速率下降(對實時應用頗有用,好比視頻會議)
4.每一條tcp鏈接只能是點到點的;udp支持一對一,一對多,多對一,多對多的交互通訊
5.tcp首部開銷20字節;udp首部開銷小,只有8字節
6.tcp通訊信道是全雙工的可靠信道;udp則是不可靠

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

在這裏插入圖片描述
protected 當前類,同包,異包子類。

73.float f=3.4;是否正確?

答:不正確。3.4是雙精度數,將雙精度型(double)賦值給浮點型(float)屬於下轉型(down-casting,也稱爲窄化)會形成精度損失,所以須要強制類型轉換float f =(float)3.4; 或者寫成float f =3.4F;

74.short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1;有錯嗎?

答:對於short s1 = 1; s1 = s1 + 1;因爲1是int類型,所以s1+1運算結果也是int 型,須要強制轉換類型才能賦值給short型。而short s1 = 1; s1 += 1;能夠正確編譯,由於s1+= 1;至關於s1 = (short)(s1 + 1);其中有隱含的強制類型轉換。

75.Java有沒有goto?

答:goto 是Java中的保留字,在目前版本的Java中沒有使用。(根據James Gosling(Java之父)編寫的《The Java Programming Language》一書的附錄中給出了一個Java關鍵字列表,其中有goto和const,可是這兩個是目前沒法使用的關鍵字,所以有些地方將其稱之爲保留字,其實保留字這個詞應該有更普遍的意義,由於熟悉C語言的程序員都知道,在系統類庫中使用過的有特殊意義的單詞或單詞的組合都被視爲保留字)

76.int和Integer有什麼區別?

答:Java是一個近乎純潔的面向對象編程語言,可是爲了編程的方便仍是引入了基本數據類型,可是爲了可以將這些基本數據類型當成對象操做,Java爲每個基本數據類型都引入了對應的包裝類型(wrapper class),int的包裝類就是Integer,從Java 5開始引入了自動裝箱/拆箱機制,使得兩者能夠相互轉換。
Java 爲每一個原始類型提供了包裝類型:

原始類型: boolean,char,byte,short,int,long,float,double
包裝類型:Boolean,Character,Byte,Short,Integer,Long,Float,Double

77.&和&&的區別?

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

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

答:一般咱們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用JVM中的棧空間;而經過new關鍵字和構造器建立的對象則放在堆空間,堆是垃圾收集器管理的主要區域,因爲如今的垃圾收集器都採用分代收集算法,因此堆空間還能夠細分爲新生代和老生代,再具體一點能夠分爲Eden、Survivor(又可分爲From Survivor和To Survivor)、Tenured;方法區和堆都是各個線程共享的內存區域,用於存儲已經被JVM加載的類信息、常量、靜態變量、JIT編譯器編譯後的代碼等數據;程序中的字面量(literal)如直接書寫的100、"hello"和常量都是放在常量池中,常量池是方法區的一部分,。棧空間操做起來最快可是棧很小,一般大量的對象都是放在堆空間,棧和堆的大小均可以經過JVM的啓動參數來進行調整,棧空間用光了會引起StackOverflowError,而堆和常量池空間不足則會引起OutOfMemoryError。

String str = new String(「hello」);

上面的語句中變量str放在棧上,用new建立出來的字符串對象放在堆上,而"hello"這個字面量是放在方法區的。

補充1:較新版本的Java(從Java 6的某個更新開始)中,因爲JIT編譯器的發展和"逃逸分析"技術的逐漸成熟,棧上分配、標量替換等優化技術使得對象必定分配在堆上這件事情已經變得不那麼絕對了。

補充2:運行時常量池至關於Class文件常量池具備動態性,Java語言並不要求常量必定只有編譯期間才能產生,運行期間也能夠將新的常量放入池中,String類的intern()方法就是這樣的。

看看下面代碼的執行結果是什麼而且比較一下Java 7之前和之後的運行結果是否一致。

String s1 = new StringBuilder("go")
    .append("od").toString();
System.out.println(s1.intern() == s1);
String s2 = new StringBuilder("ja")
    .append("va").toString();
System.out.println(s2.intern() == s2);

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

答:Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四捨五入的原理是在參數上加0.5而後進行下取整。

80.switch 是否能做用在byte 上,是否能做用在long 上,是否能做用在String上?

答:在Java 5之前,switch(expr)中,expr只能是byte、short、char、int。從Java 5開始,Java中引入了枚舉類型,expr也能夠是enum類型,從Java 7開始,expr還能夠是字符串(String),可是長整型(long)在目前全部的版本中都是不能夠的。

81.用最有效率的方法計算2乘以8?

答: 2 << 3(左移3位至關於乘以2的3次方,右移3位至關於除以2的3次方)。

補充:咱們爲編寫的類重寫hashCode方法時,可能會看到以下所示的代碼,其實咱們不太理解爲何要使用這樣的乘法運算來產生哈希碼(散列碼),並且爲何這個數是個素數,爲何一般選擇31這個數?前兩個問題的答案你能夠本身百度一下,選擇31是由於能夠用移位和減法運算來代替乘法,從而獲得更好的性能。說到這裏你可能已經想到了:31 * num 等價於(num << 5) - num,左移5位至關於乘以2的5次方再減去自身就至關於乘以31,如今的VM都能自動完成這個優化。

82.數組有沒有length()方法?String有沒有length()方法?

答:數組沒有length()方法,有length 的屬性。String 有length()方法。JavaScript中,得到字符串的長度是經過length屬性獲得的,這一點容易和Java混淆。

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

答:在最外層循環前加一個標記如A,而後用break A;能夠跳出多重循環。(Java中支持帶標籤的break和continue語句,做用有點相似於C和C++中的goto語句,可是就像要避免使用goto同樣,應該避免使用帶標籤的break和continue,由於它不會讓你的程序變得更優雅,不少時候甚至有相反的做用,因此這種語法其實不知道更好)

84.構造器(constructor)是否可被重寫(override)?

答:構造器不能被繼承,所以不能被重寫,但能夠被重載。

85.兩個對象值相同(x.equals(y) == true),但卻可有不一樣的hash code,這句話對不對?

答:不對,若是兩個對象x和y知足x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java對於eqauls方法和hashCode方法是這樣規定的:(1)若是兩個對象相同(equals方法返回true),那麼它們的hashCode值必定要相同;(2)若是兩個對象的hashCode相同,它們並不必定相同。固然,你未必要按照要求去作,可是若是你違背了上述原則就會發如今使用容器時,相同的對象能夠出如今Set集合中,同時增長新元素的效率會大大降低(對於使用哈希存儲的系統,若是哈希碼頻繁的衝突將會形成存取性能急劇降低)。

86.是否能夠繼承String類?

答:String 類是final類,不能夠被繼承。

補充:繼承String自己就是一個錯誤的行爲,對String類型最好的重用方式是關聯關係(Has-A)和依賴關係(Use-A)而不是繼承關係(Is-A)。

87.當一個對象被看成參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裏究竟是按值傳遞仍是按引用傳遞?

答:是按值傳遞。Java語言的方法調用只支持參數的按值傳遞。當一個對象實例做爲一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性能夠在被調用過程當中被改變,但在方法內部對對象引用的改變是不會影響到被調用者的。C++和C#中能夠經過傳引用或傳輸出參數來改變傳入的參數的值。在C#中能夠編寫以下所示的代碼,可是在Java中卻作不到。

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

答:方法的重載和重寫都是實現多態的方式,區別在於前者實現的是編譯時的多態性,然後者實現的是運行時的多態性。重載發生在一個類中,同名的方法若是有不一樣的參數列表(參數類型不一樣、參數個數不一樣或者兩者都不一樣)則視爲重載;重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對返回類型沒有特殊的要求。

89.描述一下JVM加載class文件的原理機制?

答:JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實現的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類文件中的類。
因爲Java的跨平臺性,通過編譯的Java源程序並非一個可執行程序,而是一個或多個類文件。當Java程序須要使用某個類時,JVM會確保這個類已經被加載、鏈接(驗證、準備和解析)和初始化。類的加載是指把類的.class文件中的數據讀入到內存中,一般是建立一個字節數組讀入.class文件,而後產生與所加載類對應的Class對象。加載完成後,Class對象還不完整,因此此時的類還不可用。當類被加載後就進入鏈接階段,這一階段包括驗證、準備(爲靜態變量分配內存並設置默認的初始值)和解析(將符號引用替換爲直接引用)三個步驟。最後JVM對類進行初始化,包括:1)若是類存在直接的父類而且這個類尚未被初始化,那麼就先初始化父類;2)若是類中存在初始化語句,就依次執行這些初始化語句。
類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類加載過程採起了父親委託機制(PDM)。PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其餘的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能爲力時才由其子類加載器自行加載。JVM不會向Java程序提供對Bootstrap的引用。下面是關於幾個類加載器的說明:

Bootstrap:通常用本地代碼實現,負責加載JVM基礎核心類庫(rt.jar);
Extension:從java.ext.dirs系統屬性所指定的目錄中加載類庫,它的父加載器是Bootstrap;
System:又叫應用類加載器,其父類是Extension。它是應用最普遍的類加載器。它從環境變量classpath或者系統屬性java.class.path所指定的目錄中加載類,是用戶自定義加載器的默認父加載器。

90.char 型變量中能不能存貯一箇中文漢字,爲何?

答:char類型能夠存儲一箇中文漢字,由於Java中使用的編碼是Unicode(不選擇任何特定的編碼,直接使用字符在字符集中的編號,這是統一的惟一方法),一個char類型佔2個字節(16比特),因此放一箇中文是沒問題的。

補充:使用Unicode意味着字符在JVM內部和外部有不一樣的表現形式,在JVM內部都是Unicode,當這個字符被從JVM內部轉移到外部時(例如存入文件系統中),須要進行編碼轉換。因此Java中有字節流和字符流,以及在字符流和字節流之間進行轉換的轉換流,如InputStreamReader和OutputStreamReader,這兩個類是字節流和字符流之間的適配器類,承擔了編碼轉換的任務;對於C程序員來講,要完成這樣的編碼轉換恐怕要依賴於union(聯合體/共用體)共享內存的特徵來實現了。

91.靜態嵌套類(Static Nested Class)和內部類(Inner Class)的不一樣?

答:Static Nested Class是被聲明爲靜態(static)的內部類,它能夠不依賴於外部類實例被實例化。而一般的內部類須要在外部類實例化後才能實例化

92.抽象類(abstract class)和接口(interface)有什麼異同?

答:抽象類和接口都不可以實例化,但能夠定義抽象類和接口類型的引用。一個類若是繼承了某個抽象類或者實現了某個接口都須要對其中的抽象方法所有進行實現,不然該類仍然須要被聲明爲抽象類。接口比抽象類更加抽象,由於抽象類中能夠定義構造器,能夠有抽象方法和具體方法,而接口中不能定義構造器並且其中的方法所有都是抽象方法。抽象類中的成員能夠是private、默認、protected、public的,而接口中的成員全都是public的。抽象類中能夠定義成員變量,而接口中定義的成員變量實際上都是常量。有抽象方法的類必須被聲明爲抽象類,而抽象類未必要有抽象方法。

93.Java 中會存在內存泄漏嗎,請簡單描述。

答:理論上Java由於有垃圾回收機制(GC)不會存在內存泄露問題(這也是Java被普遍使用於服務器端編程的一個重要緣由);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收,所以也會致使內存泄露的發生。例如Hibernate的Session(一級緩存)中的對象屬於持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,若是不及時關閉(close)或清空(flush)一級緩存就可能致使內存泄露。

94.抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被synchronized修飾?

答:都不能。抽象方法須要子類重寫,而靜態的方法是沒法被重寫的,所以兩者是矛盾的。本地方法是由本地代碼(如C代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized和方法的實現細節有關,抽象方法不涉及實現細節,所以也是相互矛盾的。

95.闡述靜態變量和實例變量的區別。

答:靜態變量是被static修飾符修飾的變量,也稱爲類變量,它屬於類,不屬於類的任何一個對象,一個類無論建立多少個對象,靜態變量在內存中有且僅有一個拷貝;實例變量必須依存於某一實例,須要先建立對象而後經過對象才能訪問到它。靜態變量能夠實現讓多個對象共享內存。

96.是否能夠從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?

答:不能夠,靜態方法只能訪問靜態成員,由於非靜態方法的調用要先建立對象,在調用靜態方法時可能對象並無被初始化。

97.如何實現對象克隆?

答:有兩種方式:
  1). 實現Cloneable接口並重寫Object類中的clone()方法;
  2). 實現Serializable接口,經過對象的序列化和反序列化實現克隆,能夠實現真正的深度克隆,

98.GC是什麼?爲何要有GC?

答:GC是垃圾收集的意思,內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會致使程序或系統的不穩定甚至崩潰,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯式操做方法。Java程序員不用擔憂內存管理,由於垃圾收集器會自動進行管理。要請求垃圾收集,能夠調用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM能夠屏蔽掉顯式的垃圾回收調用。
垃圾回收能夠有效的防止內存泄露,有效的使用能夠使用的內存。垃圾回收器一般是做爲一個單獨的低優先級的線程運行,不可預知的狀況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調用垃圾回收器對某個對象或全部對象進行垃圾回收。在Java誕生初期,垃圾回收是Java最大的亮點之一,由於服務器端的編程須要有效的防止內存泄露問題,然而時過境遷,現在Java的垃圾回收機制已經成爲被詬病的東西。移動智能終端用戶一般以爲iOS的系統比Android系統有更好的用戶體驗,其中一個深層次的緣由就在於Android系統中垃圾回收的不可預知性。

99.String s = new String(「xyz」);建立了幾個字符串對象?

兩個對象,一個是靜態區的"xyz",一個是用new建立在堆上的對象。

100.接口是否可繼承(extends)接口?抽象類是否可實現(implements)接口?抽象類是否可繼承具體類(concrete class)?

答:接口能夠繼承接口,並且支持多重繼承。抽象類能夠實現(implements)接口,抽象類可繼承具體類也能夠繼承抽象類。
舉一個多繼承的例子,咱們定義一個動物(類)既是狗(父類1)也是貓(父類2),兩個父類都有「叫」這個方法。那麼當咱們調用「叫」這個方法時,它就不知道是狗叫仍是貓叫了,這就是多重繼承的衝突。
而接口沒有具體的方法實現,因此多繼承接口也不會出現這種衝突。

101.一個".java"源文件中是否能夠包含多個類(不是內部類)?有什麼限制?

答:能夠,但一個源文件中最多隻能有一個公開類(public class)並且文件名必須和公開類的類名徹底保持一致。

102.Anonymous Inner Class(匿名內部類)是否能夠繼承其它類?是否能夠實現接口?

答:能夠繼承其餘類或實現其餘接口,在Swing編程和Android開發中經常使用此方式來實現事件監聽和回調。

103.內部類能夠引用它的包含類(外部類)的成員嗎?有沒有什麼限制?

答:一個內部類對象能夠訪問建立它的外部類對象的成員,包括私有成員。

104.數據類型之間的轉換:

如何將字符串轉換爲基本數據類型?

如何將基本數據類型轉換爲字符串?

答:

調用基本數據類型對應的包裝類中的方法parseXXX(String)或valueOf(String)便可返回相應基本類型;
一種方法是將基本數據類型與空字符串("")鏈接(+)便可得到其所對應的字符串;另外一種方法是調用String 類中的valueOf()方法返回相應字符串

105.如何實現字符串的反轉及替換?

答:方法不少,能夠本身寫實現也能夠使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,

106.怎樣將GB2312編碼的字符串轉換爲ISO-8859-1編碼的字符串?

String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");

107.日期和時間: 如何取得年月日、小時分鐘秒? 如何取得從1970年1月1日0時0分0秒到如今的毫秒數? 如何取得某月的最後一天? 如何格式化日期?

答:
問題1:建立java.util.Calendar 實例,調用其get()方法傳入不一樣的參數便可得到參數所對應的值。Java 8中能夠使用java.time.LocalDateTimel來獲取,

108.比較一下Java和JavaSciprt

答:JavaScript 與Java是兩個公司開發的不一樣的兩個產品。Java 是原Sun Microsystems公司推出的面向對象的程序設計語言,特別適合於互聯網應用程序開發;而JavaScript是Netscape公司的產品,爲了擴展Netscape瀏覽器的功能而開發的一種能夠嵌入Web頁面中運行的基於對象和事件驅動的解釋性語言。JavaScript的前身是LiveScript;而Java的前身是Oak語言。
下面對兩種語言間的異同做以下比較:

基於對象和麪向對象:Java是一種真正的面向對象的語言,即便是開發簡單的程序,必須設計對象;JavaScript是種腳本語言,它能夠用來製做與網絡無關的,與用戶交互做用的複雜軟件。它是一種基於對象(Object-Based)和事件驅動(Event-Driven)的編程語言,於是它自己提供了很是豐富的內部對象供設計人員使用。
解釋和編譯:Java的源代碼在執行以前,必須通過編譯。JavaScript是一種解釋性編程語言,其源代碼不需通過編譯,由瀏覽器解釋執行。(目前的瀏覽器幾乎都使用了JIT(即時編譯)技術來提高JavaScript的運行效率)
強類型變量和弱類型變量:Java採用強類型變量檢查,即全部變量在編譯以前必須做聲明;JavaScript中變量是弱類型的,甚至在使用變量前能夠不做聲明,JavaScript的解釋器在運行時檢查推斷其數據類型。
代碼格式不同。

109.何時用斷言(assert)?

答:斷言在軟件開發中是一種經常使用的調試方式,不少開發語言中都支持這種機制。通常來講,斷言用於保證程序最基本、關鍵的正確性。斷言檢查一般在開發和測試時開啓。爲了保證程序的執行效率,在軟件發佈後斷言檢查一般是關閉的。斷言是一個包含布爾表達式的語句,在執行這個語句時假定該表達式爲true;若是表達式的值爲false,那麼系統會報告一個AssertionError。斷言的使用以下面的代碼所示:

110.Error和Exception有什麼區別?

答:Error表示系統級的錯誤和程序沒必要處理的異常,是恢復不是不可能但很困難的狀況下的一種嚴重問題;好比內存溢出,不可能期望程序能處理這樣的狀況;Exception表示須要捕捉或者須要程序進行處理的異常,是一種設計或實現問題;也就是說,它表示若是程序運行正常,從不會發生的狀況。

111.try{}裏有一個return語句,那麼緊跟在這個try後的finally{}裏的代碼會不會被執行,何時被執行,在return前仍是後?

答:會執行,在方法返回前執行。

注意:在finally中改變返回值的作法是很差的,由於若是存在finally代碼塊,try中的return語句不會立馬返回調用者,而是記錄下返回值待finally代碼塊執行完畢以後再向調用者返回其值,而後若是在finally中修改了返回值,就會返回修改後的值。顯然,在finally中返回或者修改返回值會對程序形成很大的困擾,C#中直接用編譯錯誤的方式來阻止程序員幹這種齷齪的事情,Java中也能夠經過提高編譯器的語法檢查級別來產生警告或錯誤,Eclipse中能夠在如圖所示的地方進行設置,強烈建議將此項設置爲編譯錯誤。

112.Java語言如何進行異常處理,關鍵字:throws、throw、try、catch、finally分別如何使用?

答:Java經過面向對象的方法進行異常處理,把各類不一樣的異常進行分類,並提供了良好的接口。在Java中,每一個異常都是一個對象,它是Throwable類或其子類的實例。當一個方法出現異常後便拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法能夠捕獲到這個異常並能夠對其進行處理。Java的異常處理是經過5個關鍵詞來實現的:try、catch、throw、throws和finally。通常狀況下是用try來執行一段程序,若是系統會拋出(throw)一個異常對象,能夠經過它的類型來捕獲(catch)它,或經過老是執行代碼塊(finally)來處理;try用來指定一塊預防全部異常的程序;catch子句緊跟在try塊後面,用來指定你想要捕獲的異常的類型;throw語句用來明確地拋出一個異常;throws用來聲明一個方法可能拋出的各類異常(固然聲明異常時容許無病呻吟);finally爲確保一段代碼無論發生什麼異常情況都要被執行;try語句能夠嵌套,每當遇到一個try語句,異常的結構就會被放入異常棧中,直到全部的try語句都完成。若是下一級的try語句沒有對某種異常進行處理,異常棧就會執行出棧操做,直到遇到有處理這種異常的try語句或者最終將異常拋給JVM。

113.運行時異常與受檢異常有何異同?

答:異常表示程序運行過程當中可能出現的非正常狀態,運行時異常表示虛擬機的一般操做中可能遇到的異常,是一種常見運行錯誤,只要程序設計得沒有問題一般就不會發生。受檢異常跟程序運行的上下文環境有關,即便程序設計無誤,仍然可能因使用的問題而引起。Java編譯器要求方法必須聲明拋出可能發生的受檢異常,可是並不要求必須聲明拋出未被捕獲的運行時異常。異常和繼承同樣,是面向對象程序設計中常常被濫用的東西,在Effective Java中對異常的使用給出瞭如下指導原則:

不要將異常處理用於正常的控制流(設計良好的API不該該強迫它的調用者爲了正常的控制流而使用異常)
對能夠恢復的狀況使用受檢異常,對編程錯誤使用運行時異常
避免沒必要要的使用受檢異常(能夠經過一些狀態檢測手段來避免異常的發生)
優先使用標準的異常
每一個方法拋出的異常都要有文檔
保持異常的原子性
不要在catch中忽略掉捕獲到的異常

114.列出一些你常見的運行時異常?

答:

ArithmeticException(算術異常)
ClassCastException (類轉換異常)
IllegalArgumentException (非法參數異常)
IndexOutOfBoundsException (下標越界異常)
NullPointerException (空指針異常)
SecurityException (安全異常)

115.闡述final、finally、finalize的區別。

答:

final:修飾符(關鍵字)有三種用法:若是一個類被聲明爲final,意味着它不能再派生出新的子類,即不能被繼承,所以它和abstract是反義詞。將變量聲明爲final,能夠保證它們在使用中不被改變,被聲明爲final的變量必須在聲明時給定初值,而在之後的引用中只能讀取不可修改。被聲明爲final的方法也一樣只能使用,不能在子類中被重寫。
finally:一般放在try…catch…的後面構造老是執行代碼塊,這就意味着程序不管正常執行仍是發生異常,這裏的代碼只要JVM不關閉都能執行,能夠將釋放外部資源的代碼寫在finally塊中。
finalize:Object類中定義的方法,Java中容許使用finalize()方法在垃圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收集器在銷燬對象時調用的,經過重寫finalize()方法能夠整理系統資源或者執行其餘清理工做。

116.List、Set、Map是否繼承自Collection接口?

答:List、Set 是,Map 不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不容許有重複元素(數學中的集合也是如此),List是線性結構的容器,適用於按數值索引訪問元素的情形。

117.闡述ArrayList、Vector、LinkedList的存儲性能和特性。

答:ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增長和插入元素,它們都容許直接按序號索引元素,可是插入元素要涉及數組元素移動等內存操做,因此索引數據快而插入數據慢,Vector中的方法因爲添加了synchronized修飾,所以Vector是線程安全的容器,但性能上較ArrayList差,所以已是Java中的遺留容器。LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元經過附加的引用關聯起來,造成一個能夠按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據須要進行前向或後向遍歷,可是插入數據時只須要記錄本項的先後項便可,因此插入速度較快。Vector屬於遺留容器(Java早期的版本中提供的容器,除此以外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,可是因爲ArrayList和LinkedListed都是非線程安全的,若是遇到多個線程操做同一個容器的場景,則能夠經過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器後再使用(這是對裝潢模式的應用,將已有對象傳入另外一個類的構造器中建立新的對象來加強實現)。

118.Collection和Collections的區別?

答:Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操做,這些方法包括對容器的搜索、排序、線程安全化等等。

119. List、Map、Set三個接口存取元素時,各有什麼特色?

答:List以特定索引來存取元素,能夠有重複元素。Set不能存放重複元素(用對象的equals()方法來區分元素是否重複)。Map保存鍵值對(key-value pair)映射,映射關係能夠是一對一或多對一。Set和Map容器都有基於哈希存儲和排序樹的兩種實現版本,基於哈希存儲的版本理論存取時間複雜度爲O(1),而基於排序樹版本的實如今插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。

120.TreeMap和TreeSet在排序時如何比較元素?Collections工具類中的sort()方法如何比較元素?

答:TreeSet要求存放的對象所屬的類必須實現Comparable接口,該接口提供了比較元素的compareTo()方法,當插入元素時會回調該方法比較元素的大小。TreeMap要求存放的鍵值對映射的鍵必須實現Comparable接口從而根據鍵對元素進行排序。Collections工具類的sort方法有兩種重載的形式,第一種要求傳入的待排序容器中存放的對象必須實現Comparable接口以實現元素的比較;第二種不強制性的要求容器中的元素必須可比較,可是要求傳入第二個參數,參數是Comparator接口的子類型(須要重寫compare方法實現元素的比較),至關於一個臨時定義的排序規則,其實就是經過接口注入比較元素大小的算法,也是對回調模式的應用(Java中對函數式編程的支持)。

121.Thread類的sleep()方法和對象的wait()方法均可以讓線程暫停執行,它們有什麼區別?

答:sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其餘線程,可是對象的鎖依然保持,所以休眠時間結束後會自動恢復(線程回到就緒狀態,請參考第66題中的線程狀態轉換圖)。wait()是Object類的方法,調用對象的wait()方法致使當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(wait pool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lock pool),若是線程從新得到對象的鎖就能夠進入就緒狀態。

122.線程的sleep()方法和yield()方法有什麼區別?

答:
① sleep()方法給其餘線程運行機會時不考慮線程的優先級,所以會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;
② 線程執行sleep()方法後轉入阻塞(blocked)狀態,而執行yield()方法後轉入就緒(ready)狀態;
③ sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;
④ sleep()方法比yield()方法(跟操做系統CPU調度相關)具備更好的可移植性。

123.當一個線程進入一個對象的synchronized方法A以後,其它線程是否可進入此對象的synchronized方法B?

答:不能。其它線程只能訪問該對象的非同步方法,同步方法則不能進入。由於非靜態方法上的synchronized修飾符要求執行方法時要得到對象的鎖,若是已經進入A方法說明對象鎖已經被取走,那麼試圖進入B方法的線程就只能在等鎖池(注意不是等待池哦)中等待對象的鎖。

124.請說出與線程同步以及線程調度相關的方法。

答:

wait():使一個線程處於等待(阻塞)狀態,而且釋放所持有的對象的鎖;
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;
notify():喚醒一個處於等待狀態的線程,固然在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且與優先級無關;
notityAll():喚醒全部處於等待狀態的線程,該方法並非將對象的鎖給全部線程,而是讓它們競爭,只有得到鎖的線程才能進入就緒狀態;

125.編寫多線程程序有幾種實現方式?

答:Java 5之前實現多線程有兩種實現方法:一種是繼承Thread類;另外一種是實現Runnable接口。兩種方式都要經過重寫run()方法來定義線程的行爲,推薦使用後者,由於Java中的繼承是單繼承,一個類有一個父類,若是繼承了Thread類就沒法再繼承其餘類了,顯然使用Runnable接口更爲靈活。

126.synchronized關鍵字的用法?

答:synchronized關鍵字能夠將對象或者方法標記爲同步,以實現對對象和方法的互斥訪問,能夠用synchronized(對象) { … }定義同步代碼塊,或者在聲明方法時將synchronized做爲方法的修飾符。在第60題的例子中已經展現了synchronized關鍵字的用法。

127.舉例說明同步和異步。

答:若是系統中存在臨界資源(資源數量少於競爭資源的線程數量的資源),例如正在寫的數據之後可能被另外一個線程讀到,或者正在讀的數據可能已經被另外一個線程寫過了,那麼這些數據就必須進行同步存取(數據庫操做中的排他鎖就是最好的例子)。當應用程序在對象上調用了一個須要花費很長時間來執行的方法,而且不但願讓程序等待方法的返回時,就應該使用異步編程,在不少狀況下采用異步途徑每每更有效率。事實上,所謂的同步就是指阻塞式操做,而異步就是非阻塞式操做。

128.啓動一個線程是調用run()仍是start()方法?

答:啓動一個線程是調用start()方法,使線程所表明的虛擬處理機處於可運行狀態,這意味着它能夠由JVM 調度並執行,這並不意味着線程就會當即運行。run()方法是線程啓動後要進行回調(callback)的方法。

129.什麼是線程池(thread pool)?

答:在面向對象編程中,建立和銷燬對象是很費時間的,由於建立一個對象要獲取內存資源或者其它更多資源。在Java中更是如此,虛擬機將試圖跟蹤每個對象,以便可以在對象銷燬後進行垃圾回收。因此提升服務程序效率的一個手段就是儘量減小建立和銷燬對象的次數,特別是一些很耗資源的對象建立和銷燬,這就是」池化資源」技術產生的緣由。線程池顧名思義就是事先建立若干個可執行的線程放入一個池(容器)中,須要的時候從池中獲取線程不用自行建立,使用完畢不須要銷燬線程而是放回池中,從而減小建立和銷燬線程對象的開銷。
Java 5+中的Executor接口定義一個執行線程的工具。它的子類型即線程池接口是ExecutorService。要配置一個線程池是比較複雜的,尤爲是對於線程池的原理不是很清楚的狀況下,所以在工具類Executors裏面提供了一些靜態工廠方法,生成一些經常使用的線程池,以下所示:

newSingleThreadExecutor:建立一個單線程的線程池。這個線程池只有一個線程在工做,也就是至關於單線程串行執行全部任務。若是這個惟一的線程由於異常結束,那麼會有一個新的線程來替代它。此線程池保證全部任務的執行順序按照任務的提交順序執行。
newFixedThreadPool:建立固定大小的線程池。每次提交一個任務就建立一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,若是某個線程由於執行異常而結束,那麼線程池會補充一個新線程。
newCachedThreadPool:建立一個可緩存的線程池。若是線程池的大小超過了處理任務所須要的線程,那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增長時,此線程池又能夠智能的添加新線程來處理任務。此線程池不會對線程池大小作限制,線程池大小徹底依賴於操做系統(或者說JVM)可以建立的最大線程大小。
newScheduledThreadPool:建立一個大小無限的線程池。此線程池支持定時以及週期性執行任務的需求。

130.簡述synchronized 和java.util.concurrent.locks.Lock的異同?

答:Lock是Java 5之後引入的新的API,和關鍵字synchronized相比主要相同點:Lock 能完成synchronized所實現的全部功能;主要不一樣點:Lock有比synchronized更精確的線程語義和更好的性能,並且不強制性的要求必定要得到鎖。synchronized會自動釋放鎖,而Lock必定要求程序員手工釋放,而且最好在finally 塊中釋放(這是釋放外部資源的最好的地方)。

131.Java中如何實現序列化,有什麼意義?

答:序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。能夠對流化後的對象進行讀寫操做,也可將流化後的對象傳輸於網絡之間。序列化是爲了解決對象流讀寫操做時可能引起的問題(若是不進行序列化可能會存在數據亂序的問題)。
要實現序列化,須要讓一個類實現Serializable接口,該接口是一個標識性接口,標註該類對象是可被序列化的,而後使用一個輸出流來構造一個對象輸出流並經過writeObject(Object)方法就能夠將實現對象寫出(即保存其狀態);若是須要反序列化則能夠用一個輸入流創建對象輸入流,而後經過readObject方法從流中讀取對象。序列化除了可以實現對象的持久化以外,還可以用於對象的深度克隆

132.Java中有幾種類型的流?

答:字節流和字符流。字節流繼承於InputStream、OutputStream,字符流繼承於Reader、Writer。在 java.io 包中還有許多其餘的流,主要是爲了提升性能和使用方便。關於Java的I/O須要注意的有兩點:一是兩種對稱性(輸入和輸出的對稱性,字節和字符的對稱性);二是兩種設計模式(適配器模式和裝潢模式)。另外Java中的流不一樣於C#的是它只有一個維度一個方向。

133.寫一個方法,輸入一個文件名和一個字符串,統計這個字符串在這個文件中出現的次數。

import java.io.BufferedReader;
import java.io.FileReader;
 
public final class MyUtil {
 
    // 工具類中的方法都是靜態方式訪問的所以將構造器私有不容許建立對象(絕對好習慣)
    private MyUtil() {
        throw new AssertionError();
    }
 
    /**
     * 統計給定文件中給定字符串的出現次數
     * 
     * @param filename  文件名
     * @param word 字符串
     * @return 字符串在文件中出現的次數
     */
    public static int countWordInFile(String filename, String word) {
        int counter = 0;
        try (FileReader fr = new FileReader(filename)) {
            try (BufferedReader br = new BufferedReader(fr)) {
                String line = null;
                while ((line = br.readLine()) != null) {
                    int index = -1;
                    while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) {
                        counter++;
                        line = line.substring(index + word.length());
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return counter;
    }
 
}

134.如何用Java代碼列出一個目錄下全部的文件?

import java.io.File;
 
class Test12 {
 
    public static void main(String[] args) {
        File f = new File("/Users/nnngu/Downloads");
        for(File temp : f.listFiles()) {
            if(temp.isFile()) {
                System.out.println(temp.getName());
            }
        }
    }
}

135.XML文檔定義有幾種形式?它們之間有何本質區別?解析XML文檔有哪幾種方式?

答:XML文檔定義分爲DTD和Schema兩種形式,兩者都是對XML語法的約束,其本質區別在於Schema自己也是一個XML文件,能夠被XML解析器解析,並且能夠爲XML承載的數據定義類型,約束能力較之DTD更強大。對XML的解析主要有DOM(文檔對象模型,Document Object Model)、SAX(Simple API for XML)和StAX(Java 6中引入的新的解析XML的方式,Streaming API for XML),其中DOM處理大型文件時其性能降低的很是厲害,這個問題是由DOM樹結構佔用的內存較多形成的,並且DOM解析方式必須在解析文件以前把整個文檔裝入內存,適合對XML的隨機訪問(典型的用空間換取時間的策略);SAX是事件驅動型的XML解析方式,它順序讀取XML文件,不須要一次所有裝載整個文件。當遇到像文件開頭,文檔結束,或者標籤開頭與標籤結束時,它會觸發一個事件,用戶經過事件回調代碼來處理XML文件,適合對XML的順序訪問;顧名思義,StAX把重點放在流上,實際上StAX與其餘解析方式的本質區別就在於應用程序可以把XML做爲一個事件流來處理。將XML做爲一組事件來處理的想法並不新穎(SAX就是這樣作的),但不一樣之處在於StAX容許應用程序代碼把這些事件逐個拉出來,而不用提供在解析器方便時從解析器中接收事件的處理程序。

136.闡述JDBC操做數據庫的步驟

加載驅動。
建立鏈接。
建立語句。
執行語句。
處理結果。
關閉資源。

137.Statement和PreparedStatement有什麼區別?哪一個性能更好?

答:與Statement相比,①PreparedStatement接口表明預編譯的語句,它主要的優點在於能夠減小SQL的編譯錯誤並增長SQL的安全性(減小SQL注射攻擊的可能性);②PreparedStatement中的SQL語句是能夠帶參數的,避免了用字符串鏈接拼接SQL語句的麻煩和不安全;③當批量處理SQL或頻繁執行相同的查詢時,PreparedStatement有明顯的性能上的優點,因爲數據庫能夠將編譯優化後的SQL語句緩存起來,下次執行相同結構的語句時就會很快(不用再次編譯和生成執行計劃)。

138.使用JDBC操做數據庫時,如何提高讀取數據的性能?如何提高更新數據的性能?

答:要提高讀取數據的性能,能夠指定經過結果集(ResultSet)對象的setFetchSize()方法指定每次抓取的記錄數(典型的空間換時間策略);要提高更新數據的性能能夠使用PreparedStatement語句構建批處理,將若干SQL語句置於一個批處理中執行。

139.什麼是DAO模式?

答:DAO(Data Access Object)顧名思義是一個爲數據庫或其餘持久化機制提供了抽象接口的對象,在不暴露底層持久化方案實現細節的前提下提供了各類數據訪問操做。在實際的開發中,應該將全部對數據源的訪問操做進行抽象化後封裝在一個公共API中。用程序設計語言來講,就是創建一個接口,接口中定義了此應用程序中將會用到的全部事務方法。在這個應用程序中,當須要和數據源進行交互的時候則使用這個接口,而且編寫一個單獨的類來實現這個接口,在邏輯上該類對應一個特定的數據存儲。DAO模式實際上包含了兩個模式,一是Data Accessor(數據訪問器),二是Data Object(數據對象),前者要解決如何訪問數據的問題,然後者要解決的是如何用對象封裝數據。

140.JDBC中如何進行事務處理?

答:Connection提供了事務處理的方法,經過調用setAutoCommit(false)能夠設置手動提交事務;當事務完成後用commit()顯式提交事務;若是在事務處理過程當中發生異常則經過rollback()進行事務回滾。除此以外,從JDBC 3.0中還引入了Savepoint(保存點)的概念,容許經過代碼設置保存點並讓事務回滾到指定的保存點。

141.簡述正則表達式及其用途。

答:在編寫處理字符串的程序時,常常會有查找符合某些複雜規則的字符串的須要。正則表達式就是用於描述這些規則的工具。換句話說,正則表達式就是記錄文本規則的代碼。

142.Java中是如何支持正則表達式操做的?

答:Java中的String類提供了支持正則表達式操做的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中能夠用Pattern類表示正則表達式對象,它提供了豐富的API進行各類正則表達式操做

143.得到一個類的類對象有哪些方式?

方法1:類型.class,例如:String.class
方法2:對象.getClass(),例如:「hello」.getClass()
方法3:Class.forName(),例如:Class.forName(「java.lang.String」)

144.如何經過反射建立對象?

方法1:經過類對象調用newInstance()方法,例如:String.class.newInstance()
方法2:經過類對象的getConstructor()或getDeclaredConstructor()方法得到構造器(Constructor)對象並調用其newInstance()方法建立對象,例如:String.class.getConstructor(String.class).newInstance(「Hello」);

145.如何經過反射獲取和設置對象私有字段的值?

答:能夠經過類對象的getDeclaredField()方法得到字段(Field)對象,而後再經過字段對象的setAccessible(true)將其設置爲能夠訪問,接下來就能夠經過get/set方法來獲取/設置字段的值了。下面的代碼實現了一個反射的工具類,其中的兩個靜態方法分別用於獲取和設置私有字段的值,字段能夠是基本類型也能夠是對象類型且支持多級對象操做,例如ReflectionUtil.get(dog, 「owner.car.engine.id」);能夠得到dog對象的主人的汽車的引擎的ID號。

146.簡述一下面向對象的"六原則一法則"。

答:

單一職責原則:一個類只作它該作的事情。(單一職責原則想表達的就是"高內聚",寫代碼最終極的原則只有六個字"高內聚、低耦合",就如同葵花寶典或辟邪劍譜的中心思想就八個字"欲練此功必先自宮",所謂的高內聚就是一個代碼模塊只完成一項功能,在面向對象中,若是隻讓一個類完成它該作的事,而不涉及與它無關的領域就是踐行了高內聚的原則,這個類就只有單一職責。咱們都知道一句話叫"由於專一,因此專業",一個對象若是承擔太多的職責,那麼註定它什麼都作很差。這個世界上任何好的東西都有兩個特徵,一個是功能單一,好的相機絕對不是電視購物裏面賣的那種一個機器有一百多種功能的,它基本上只能照相;另外一個是模塊化,好的自行車是組裝車,從減震叉、剎車到變速器,全部的部件都是能夠拆卸和從新組裝的,好的乒乓球拍也不是成品拍,必定是底板和膠皮能夠拆分和自行組裝的,一個好的軟件系統,它裏面的每一個功能模塊也應該是能夠輕易的拿到其餘系統中使用的,這樣才能實現軟件複用的目標。)

開閉原則:軟件實體應當對擴展開放,對修改關閉。(在理想的狀態下,當咱們須要爲一個軟件系統增長新功能時,只須要從原來的系統派生出一些新類就能夠,不須要修改原來的任何一行代碼。要作到開閉有兩個要點:①抽象是關鍵,一個系統中若是沒有抽象類或接口系統就沒有擴展點;②封裝可變性,將系統中的各類可變因素封裝到一個繼承結構中,若是多個可變因素混雜在一塊兒,系統將變得複雜而混亂,若是不清楚如何封裝可變性,能夠參考《設計模式精解》一書中對橋樑模式的講解的章節。)

依賴倒轉原則:面向接口編程。(該原則說得直白和具體一些就是聲明方法的參數類型、方法的返回類型、變量的引用類型時,儘量使用抽象類型而不用具體類型,由於抽象類型能夠被它的任何一個子類型所替代,請參考下面的里氏替換原則。)
里氏替換原則:任什麼時候候均可以用子類型替換掉父類型。(關於里氏替換原則的描述,Barbara Liskov女士的描述比這個要複雜得多,但簡單的說就是能用父類型的地方就必定能使用子類型。里氏替換原則能夠檢查繼承關係是否合理,若是一個繼承關係違背了里氏替換原則,那麼這個繼承關係必定是錯誤的,須要對代碼進行重構。例如讓貓繼承狗,或者狗繼承貓,又或者讓正方形繼承長方形都是錯誤的繼承關係,由於你很容易找到違反里氏替換原則的場景。須要注意的是:子類必定是增長父類的能力而不是減小父類的能力,由於子類比父類的能力更多,把能力多的對象當成能力少的對象來用固然沒有任何問題。)

接口隔離原則:接口要小而專,毫不能大而全。(臃腫的接口是對接口的污染,既然接口表示能力,那麼一個接口只應該描述一種能力,接口也應該是高度內聚的。例如,琴棋書畫就應該分別設計爲四個接口,而不該設計成一個接口中的四個方法,由於若是設計成一個接口中的四個方法,那麼這個接口很難用,畢竟琴棋書畫四樣都精通的人仍是少數,而若是設計成四個接口,會幾項就實現幾個接口,這樣的話每一個接口被複用的可能性是很高的。Java中的接口表明能力、表明約定、表明角色,可否正確的使用接口必定是編程水平高低的重要標識。)

合成聚合複用原則:優先使用聚合或合成關係複用代碼。(經過繼承來複用代碼是面向對象程序設計中被濫用得最多的東西,由於全部的教科書都無一例外的對繼承進行了鼓吹從而誤導了初學者,類與類之間簡單的說有三種關係,Is-A關係、Has-A關係、Use-A關係,分別表明繼承、關聯和依賴。其中,關聯關係根據其關聯的強度又能夠進一步劃分爲關聯、聚合和合成,但說白了都是Has-A關係,合成聚合複用原則想表達的是優先考慮Has-A關係而不是Is-A關係複用代碼,緣由嘛能夠本身從百度上找到一萬個理由,須要說明的是,即便在Java的API中也有很多濫用繼承的例子,例如Properties類繼承了Hashtable類,Stack類繼承了Vector類,這些繼承明顯就是錯誤的,更好的作法是在Properties類中放置一個Hashtable類型的成員而且將其鍵和值都設置爲字符串來存儲數據,而Stack類的設計也應該是在Stack類中放一個Vector對象來存儲數據。記住:任什麼時候候都不要繼承工具類,工具是能夠擁有並能夠使用的,而不是拿來繼承的。)

迪米特法則:迪米特法則又叫最少知識原則,一個對象應當對其餘對象有儘量少的瞭解。(迪米特法則簡單的說就是如何作到"低耦合",門面模式和調停者模式就是對迪米特法則的踐行。對於門面模式能夠舉一個簡單的例子,你去一家公司洽談業務,你不須要了解這個公司內部是如何運做的,你甚至能夠對這個公司一無所知,去的時候只須要找到公司入口處的前臺美女,告訴她們你要作什麼,她們會找到合適的人跟你接洽,前臺的美女就是公司這個系統的門面。再複雜的系統均可覺得用戶提供一個簡單的門面,Java Web開發中做爲前端控制器的Servlet或Filter不就是一個門面嗎,瀏覽器對服務器的運做方式一無所知,可是經過前端控制器就可以根據你的請求獲得相應的服務。調停者模式也能夠舉一個簡單的例子來講明,例如一臺計算機,CPU、內存、硬盤、顯卡、聲卡各類設備須要相互配合才能很好的工做,可是若是這些東西都直接鏈接到一塊兒,計算機的佈線將異常複雜,在這種狀況下,主板做爲一個調停者的身份出現,它將各個設備鏈接在一塊兒而不須要每一個設備之間直接交換數據,這樣就減少了系統的耦合度和複雜度,以下圖所示。迪米特法則用通俗的話來將就是不要和陌生人打交道,若是真的須要,找一個本身的朋友,讓他替你和陌生人打交道。)

147.簡述一下你瞭解的設計模式。

答:所謂設計模式,就是一套被反覆使用的代碼設計經驗的總結(情境中一個問題通過證明的一個解決方案)。使用設計模式是爲了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。設計模式令人們能夠更加簡單方便的複用成功的設計和體系結構。將已證明的技術表述成設計模式也會使新系統開發者更加容易理解其設計思路。
在GoF的《Design Patterns: Elements of Reusable Object-Oriented Software》中給出了三類(建立型[對類的實例化過程的抽象化]、結構型[描述如何將類或對象結合在一塊兒造成更大的結構]、行爲型[對在不一樣的對象之間劃分責任和算法的抽象化])共23種設計模式,包括:Abstract Factory(抽象工廠模式),Builder(建造者模式),Factory Method(工廠方法模式),Prototype(原始模型模式),Singleton(單例模式);Facade(門面模式),Adapter(適配器模式),Bridge(橋樑模式),Composite(合成模式),Decorator(裝飾模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解釋器模式),Visitor(訪問者模式),Iterator(迭代子模式),Mediator(調停者模式),Memento(備忘錄模式),Observer(觀察者模式),State(狀態模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(責任鏈模式)。
面試被問到關於設計模式的知識時,能夠揀最經常使用的做答,例如:

工廠模式:工廠類能夠根據條件生成不一樣的子類實例,這些子類有一個公共的抽象父類而且實現了相同的方法,可是這些方法針對不一樣的數據進行了不一樣的操做(多態方法)。當獲得子類的實例後,開發人員能夠調用基類中的方法而沒必要考慮到底返回的是哪個子類的實例。

代理模式:給一個對象提供一個代理對象,並由代理對象控制原對象的引用。實際開發中,按照使用目的的不一樣,代理能夠分爲:遠程代理、虛擬代理、保護代理、Cache代理、防火牆代理、同步化代理、智能引用代理。

適配器模式:把一個類的接口變換成客戶端所期待的另外一種接口,從而使本來因接口不匹配而沒法在一塊兒使用的類可以一塊兒工做。
模板方法模式:提供一個抽象類,將部分邏輯以具體方法或構造器的形式實現,而後聲明一些抽象方法來迫使子類實現剩餘的邏輯。不一樣的子類能夠以不一樣的方式實現這些抽象方法(多態實現),從而實現不一樣的業務邏輯。
除此以外,還能夠講講上面提到的門面模式、橋樑模式、單例模式、裝潢模式(Collections工具類和I/O系統中都使用裝潢模式)等,反正基本原則就是揀本身最熟悉的、用得最多的做答,以避免言多必失。

148.用Java寫一個冒泡排序。

import java.util.Comparator;
 
/**
 * 排序器接口(策略模式: 將算法封裝到具備共同接口的獨立的類中使得它們能夠相互替換)
 * @author nnngu
 *
 */
public interface Sorter {
 
   /**
    * 排序
    * @param list 待排序的數組
    */
   public <T extends Comparable<T>> void sort(T[] list);
 
   /**
    * 排序
    * @param list 待排序的數組
    * @param comp 比較兩個對象的比較器
    */
   public <T> void sort(T[] list, Comparator<T> comp);
}


import java.util.Comparator;
 
/**
 * 冒泡排序
 * 
 * @author nnngu
 *
 */
public class BubbleSorter implements Sorter {
 
    @Override
    public <T extends Comparable<T>> void sort(T[] list) {
        boolean swapped = true;
        for (int i = 1, len = list.length; i < len && swapped; ++i) {
            swapped = false;
            for (int j = 0; j < len - i; ++j) {
                if (list[j].compareTo(list[j + 1]) > 0) {
                    T temp = list[j];
                    list[j] = list[j + 1];
                    list[j + 1] = temp;
                    swapped = true;
                }
            }
        }
    }
 
    @Override
    public <T> void sort(T[] list, Comparator<T> comp) {
        boolean swapped = true;
        for (int i = 1, len = list.length; i < len && swapped; ++i) {
            swapped = false;
            for (int j = 0; j < len - i; ++j) {
                if (comp.compare(list[j], list[j + 1]) > 0) {
                    T temp = list[j];
                    list[j] = list[j + 1];
                    list[j + 1] = temp;
                    swapped = true;
                }
            }
        }
    }
}

做者:Java程序員-張凱
來源:CSDN
原文:
https://blog.csdn.net/qq_41701956/article/details/88615277
https://blog.csdn.net/qq_41701956/article/details/88572728