JavaWeb相關
1、編碼問題(Get\POST)
2、集合(map) List 有序(存取), Set無序
3、常用類(String、servlet、異常類、集合、Thread、Number、Double、system)
4、request、response
5、字符轉換===>網絡中傳輸的是字節數組,String編碼成字節數組,收到后解碼顯示
6、轉發與重定向
7、參數傳遞
8、會話跟蹤的四種實現方式
9、cookie
10、session
11、表單域
12、URL重寫
13、Servlet
14、Filter
15、對象的初始化
16、Error.jsp
17、Properties
18、日志
19、\ 和 /
20、反射(xml、)
21、內聯函數
22、Volatile
23、ThreadLocal:線程局部變量
24、transient
25、JVM相關(類的加載和執行)
26、版本區別(可變參數、枚舉)
27、數據庫(JDBC、DBMS)
28、Web容器
30、常用API(String、集合、Thread)
31、JSP
32、事件處理模型
33、java特點
34、多線程(thread、runnable、collable、condition)
35、良好的代碼習慣
36、Java的三大注解( 由虛擬器控制給出注解,提示開發人員注意編碼規則 )
37、內聯函數
38、存根類(Stub)
39、擴展方法
40、數組復制
41、設計模式 42、項目 43、框架
准備明年開始找工作,所有刷了牛客app上的900多道Java相關的筆試題,
整理了答案下面的 精華知識,以備不時之需。如有不合理之處,萬望知會。
JavaWeb相關:集合、多線程、JVM、常用類、版本區別、
1、編碼問題(Get\POST)
① html頁面:瀏覽器會根據<http header:content-type=text/html; charset=”UTF-8”>的值來決定用什么encoding(編碼),離線的本地html要在meta中指定,不指定會采用默認的編碼<meta http-equiv=”Content-Type” content=”text/html”; charset=”UTF-8”>。
② Request :request.setCharacterEncoding(“UTF-8”)應用於通過getParameter()獲取字符串,只對POST有效。必須設置在servlet中getParameter()方法被調用之前,原因是:只有在第一次調用getParameter()方法時會查詢encoding編碼格式,后續的getParameter將不再查詢編碼格式。
對於GET提交,get提交的內容存在URL中,需在Tomcat的server.xml設置,在Connector標簽中設置生成URI時的編碼格式 URIEncoding=”UTF-8”。(個人理解為 針對URI這一特殊類型數據,在server中統一設置編碼格式,不管是在JSP還是Servlet中出現,都使用統一的解碼方式,避免了亂碼的發生)。默認為ISO8859-1。
③ Resopnse :response.setContentType(“text/html”;charset=”UTF-8”)是指定HTTP響應的編碼,同時指定瀏覽器(JSP)的顯示編碼,顯示編碼不一定在JSP中有效果,因為JSP中設置的編碼格式優先級更高。
response.setCharacterEncoding(“UTF-8”)的作用是設置HTTP的響應編碼,設置應在getWriter和response被提交之前。(個人理解為 此編碼的設置是針對要返回的數據進行編碼生成response,再返回)。
④ JSP:<%@page ContentType=”text/html;charset=UTF-8”%>
<%@page pageEncoding=”charset=UTF-8”%>
以上兩種編碼只有一種有效,用於設置 頁面的顯示編碼。
如果頁面中使用include標簽導入了其他的JSP,<%@ include file=”BB.jsp”%>設置的BB.jsp中不能再設置編碼,<jsp:include page=”BB.jsp”/>設置,BB.jsp中還可以設置編碼集。
對於URL和URI的區別。請看:https://www.cnblogs.com/hust-ghtao/p/4724885.html
2、集合(map) List 有序(存取), Set無序
集合主要有Vector、HashTable、ArrayList、HashMap、stack
1) Vector 默認初始化容量為10,擴容為1倍擴容。比ArrayList多了同步機制,效率較低,線程安全,在內存中占用連續的空間,當數據量大時,會分配更大的連續空間。如果Vector定義為Object類型,則可以存放任意類型,已棄用。
2) HashTable 默認初始化容量為11,擴容為2倍。比hashmap多了同步機制,是線程安全的,對整張哈希表加鎖。key、value都不可為null,存儲的key為對象的hashcode,已棄用。
3) concurrentHashMap提供一組和HashMap功能相同但線程安全的方法。將Hash表分為16桶(segment),每次只對需要的桶加鎖。在JDK1.8之后,可以做到讀取不加鎖,其內部結構可以在寫操作時將鎖粒度盡量的小,鎖區變小。ConcurrentHashMap並不再是分段鎖,而是更細粒度的鎖,只是在修改map時對鏈表頭加鎖。(紅黑樹根)
4) HashMap 默認初始化容量為16,擴容為2倍+1。未進行同步考慮,是線程不安全的,key、value都可以為null,判斷key=null;的鍵是否存在,應該用containsKey方法,並不能用get方法。因為get返回null,即可表示null鍵也可表示不存在。存儲的key重新計算hash值(+salt?).
采用快速失敗機制(Fail-Fast),
5) HashSet內部使用Map保存數據,即將HashSet的數據hashcode做key,添加一次須比較兩次,hashcode、equals。
6) ArrayList 實現了List接口,內部基於數組結構實現存儲,隨機訪問速度快。默認初始化容量為10,擴容為1.5倍擴容。
ArrayList在刪除元素后,剩余元素會依次向前移動,因此下標會變。
有三個構造函數。
Arraylist()構造一個初始化容量為10的空列表。
Arraylist(Collection<? extends E> c)構造一個包含指定collection的元素列表,按迭代器返回它們的順序。?
Arraylist(int initialCapacity)構造一個指定容量列表的空列表。
其他方法:
remove()方法調用的是remove(int index);而不是remove(Object o); 因此刪除index索引出元素。
7) LinkedList實現了List接口,內部基於鏈表結構實現存儲,增刪快。
8) LinkedBlockingQueue:基於鏈接節點的可選限定的blocking queue(先進先出)。頭部最長,尾部最短,鏈接隊列通常具有比基於陣列的隊列更高的吞吐量,但在並發應用程序中可預測性能較低。
blocking queue:說明不接受null元素,可能是容量有限的,表示不再添加項目實現是線程安全的。
9) PriorityQueue:基於優先級堆的無限優先級queue。優先級隊列的元素根據它們的有序natural ordering或由一個Comparator在隊列構造的時候提供,這取決於所使用的構造方法。優先級隊列不允許null元素,自然排序的優先級隊列也不允許插入不可比較的對象(可能導致ClassCastException)。此實現不同步,多線程不應同時訪問PriorityQueue實例,而應該使用PriorityBlockingQueue類(線程安全)。
10) ConcurrentLinkedQueue :基於鏈接節點的無界並發deque(deque是雙端隊列),並發插入,刪除和訪問可以跨多個線程安全執行,不允許null元素。
7)AbstractSet類實現了set接口,HashSet繼承AbstractSet類,同時實現set接口。
6) stack堆棧類,繼承了vector.
7) enumeration 枚舉,相當於迭代器
集合的實現問題圖:
Map:
8) 對於線程不安全且使用迭代器的集合,采用快速失敗機制(fail-Fast)。多線程訪問中如果使用迭代器過程中,有其他線程修改了集合對象結構,可能會拋出ConcurrentModificationException,所謂快速失敗機制。在迭代器創建之后,如果從結構上對映射進行修改,除非使用迭代器本身的remove方法。
9) HashTable 和 HashMap的區別:
1) 繼承不同
public class HashTable extends Dictionary implements Map
public class HashMap extends AbstractMap implements Map
2) 同步問題
HashTable 中方法是同步的,而HashMap中方法在缺省的情況下是同步的,需要自己添加同步。
3) null 的問題:
HashTable中,key、value都不允許出現null值,
HashMap中,null可以作為鍵,這樣的鍵只有一個,可以有多個value=null,需要自己增加同步。
4) 遍歷方式不同:
HashTable、HashMap都使用了Iterator,而由於歷史原因,HashTable還使用了Enumeration的方式,
5) 哈希值不同:
HashTable直接使用對象的hashcode,而HashMap重新計算hash值。
6) 初始化和擴容:
HashTable和HashMap內部實現都是數組初始化大小和擴容方式。
HashTable的Hash數組默認為11,擴容為old*2+1;
HashMap的hash數組默認值為16,而且一定是2的指數擴容。
Java.util.Collection是一個集合接口,提供了對集合對象進行基本操作的通用接口方法,Collection接口的意義是為各種具體的集合提供最大化的統一操作方式。
Java.util.Collections是一個包裝類,包括有各種有關集合操作的靜態方法,不能實例化,就是一個工具類,服務於Java的Collection框架。
Collections 類提供了sychronizedXxx()方法,可以將指定集合包裝成線程安全的集合。
比如:List list = Collections.synchronizedList(new ArrayList());
Set set = Collections.synchronizedSet(new HashSet());
3、常用類(String、servlet、異常類、集合、Thread、Number、Double、system)
String : 用char[]數組實現,結尾不用”\0”。
String str = “he”+new String(); 運行期間生成的--->指向堆內存???
new String(“22”) 實際上創建了2個String對象,字符串常量池--存在方法區和堆中
String s=”a”+”b”+”c”; 編譯期完成。
String類是final類,成員方法默認為final方法,底層是char()數組來保存,沒有“/0”
對String對象的任何改變都不會影響到原對象。
當代碼中出現字面量形式創建字符串對象時,JVM首先會對字面量進行檢查,如果常量池存在相同內容引用,則將引用返回,否則新的字符串對象被創建,然后將對象放到字符串常量池,並返回此引用。
方法:
(1) String.toUpperCase();==>轉換為大寫,有返回值
(2) string.replace(‘f’,’F’); ==>用F替代f,無返回值(參數為char和charSequence)
(3) string.replaceAll(‘regex’,’’);==>all 匹配的是正則表達式(.匹配各個字符)
(4) string.equals()==>String 重寫了Object類的方法
Servlet 相關:
GenericServlet 抽象類給出了設計servlet的一些骨架,定義了servlet的生命周期,還有一些得到名字、配置、初始化參數的方法,設計與應用層無關。
service 方法是在servlet生命周期中的服務器,默認在HttpServlet類中實現,根據Http請求方法,將請求分發到doGet、doPost等方法實現。
javax.servlet.GenericServlet接口實現了javax.servlet.Servlet接口,且javax.servlet.http.HttpServlet是javax.servlet.GenericServlet子類。
Servlet的生命周期:
**************************************************************
***********
****此處貼圖 Servlet的生命周期圖
servlet處於服務器進程中,通過多線程方式運行其service方法,一個實例可以服務於多個請求,並且其一般不會銷毀,而CGI對每個請求都產生新的線程,服務完成后就銷毀,效率低,且不可移植。
異常:try-catch-finally try/catch 拋出異常會增加更大的開銷。
如果try的return有執行語句,例如:return i--; i--會執行,而return不會執行,進入finally。(finally一定會執行,除非try/catch中有 system.exit(0))退出。
finally中的語句不能影響try/catch中已經確定的i值,(可以說try/catch可以傳遞值到finally中,finally就像一個方法,i值就像一個參數,並不能把值傳遞回去)。最后從try中返回出i在try中的值。
結論:return 並不是函數的最終出口,也就是說遇到return要考慮是否還有finally要執行。如果存在funally代碼塊,會在return之前執行finally中的代碼。
①. try、catch、finally都有return語句,返回finally的值。(try會執行return之后的語句,例如:i--);
②. 僅try、catch中有return語句。沒有異常,執行完finally,返回i在try塊中的值。
③. try中拋出異常,try、catch、finally中都有return,返回finally中的值。
④. try中拋出異常,try、catch中都有return,返回catch中的值。
⑤. try、catch中都出現異常,在finally中有返回,返回finally中的值。
finally中不建議放return語句,return語句可以放在try和catch里面和函數的最后。
finally語句中一般放置 釋放資源、關閉數據庫、關閉文件等操作語句。
當一個方法在運行時出現未catch的異常,則這個方法終止,但整個程序不終止。
異常分類:
所有的異常都繼承自java.lang.Exception類。
檢查性異常:不處理編譯出錯,===》非運行時異常 一般dao中throws拋,service中catch
非檢查性異常:如果有拋出直接拋到控制台,==》RuntimeException 運行時異常Java編譯器不會檢查。
異常分類圖
異常指程序運行時(非編譯)所發生的錯誤,jvm將錯誤以異常形式拋出。
error類主要是運行時,邏輯錯誤導致的,jvm停止,
exception表示可恢復異常,包括檢查性異常和運行性異常
檢查性異常多包括IO異常、SQl異常,多發生在編譯期,通過try/catch捕捉。
運行性異常一般都上拋,直到遇到處理代碼,多線程用run()拋出,單線程用main()拋出。
Thread類可以被繼承,用於創建線程。
Number類可以被繼承,Integer和Float都是其子類。
Double和Math類都被final修飾,不可繼承。
ClassLoader可以被繼承,用戶可以自定義類加載器。
Math類的方法:
Math.cos為計算弧度的余弦值,Math.toRadians 方法將角度轉換為弧度。
java.lang 包是java語言的核心包,lang是language的縮寫,包括:基本的類型、包裝類型等,Integer、String等,由解釋器引入。
4、request、response
request.getParameter(“xxx”);獲取http提交的數據,返回值為字符串。
request.getAttibute(“xxx”);獲取request域中存在的對象,返回對象。
5、字符轉換===>網絡中傳輸的是字節數組,String編碼成字節數組,收到后解碼顯示
字符流 = 字節流 + 編碼集
1)GBK編碼字節流到UTF-8編碼字節流的轉換:dst=new String(src,”GBK”).getBytes(“UTF-8”);
new String(src,”GBK”):將一個字節數組編碼成一個String。===> 字符串具有
str.getBytes(“UTF-8”): 將一個string解碼成一個數組數組。 ===> 編碼格式
2)將ISO-8859-1字符串轉換成GB2312編碼:
new String(“ISO-8859-1”.getBytes(“ISO-8859-1”),”GB2312”); 字符串==>字節數組==>字符串
String UTF-8str = new String(oldGBKStr.getBytes(“GBK”),”UTF-8”);
字符串解碼成字符數組,字節數組編碼成字符串。
實際的編碼國際化常用手段利用ResourceBundler類,根據Local的不同,選擇性選取與Local對應后綴的Properties文件。
6、轉發與重定向
forward(請求轉發):發送一次請求,將表單數據或封裝到url中的數據一並轉發到新頁面。
redirect(重定向):發送兩次請求,一次請求會收到302狀態碼,第二次請求收到新地址。
1)response.setStatus(302);response.addHeader("Location","URL");
2)response.sendRedirect("URL");
1)從地址欄顯示看:
forward是服務器請求資源,服務器直接訪問目標中的URI獲取響應,經響應發送給瀏覽器。
redirect服務器發送一個狀態碼302,告訴瀏覽器去請求地址(location),url可以是其他應用。
2)從數據共享來說:
forward轉發頁面和轉發到的頁面可以共享request中的內容。redirect不能共享。
3)從運用應用方面:
forward 用於登錄注冊頁面
redirect 用於注銷登錄返回主頁面或跳轉其他網站,不再使用response輸出數據,否則會異常。
4)從效率看
forward 效率高
redirect 效率低
7、參數傳遞
基本類型傳遞值,引用類型傳遞地址,在方法中,可根據地址改變引用類型的成員變量值。
值傳遞不可以改變原變量的內容和地址(僅副本做局部變量)。
引用傳遞不可以改變原變量地址,但可通過引用改變值。
一個方法不能修改一個基本數據類型的參數(數值、布爾),===>值傳遞
一個方法可以改變一個對象(引用)的值,一個方法不可改變對象的原引用。==>引用類型
若將一個變量(常量)賦值給一個引用類型,則等於new一次引用類型對象,與方法外沒有關系。????
8、會話跟蹤的四種實現方式
1) 表單域:<input type=”hidden”>,非常適合需要大量數據存儲的會話應用
2) URL重寫:URL可以在后面附加參數,和服務器的請求一起發送,url&name=value
3) Cookie:Cookie是一個小的,已命名的數據元素,服務器使用set-Cookie頭標記它為HTTP響應的一部分,發送給客戶端,客戶端保存cookie的值,在對同一服務器的后續請求中使用cookie將內容返回給服務器,cookie保存在客戶端,可設置保存時間。(session的Id存儲在cookie中)。
4) session:使用setAttribute(String str,Object obj)方法將對象捆綁到一個會話上。
每個session對象有一個唯一的Id,保存在客戶端的Cookie中,關閉瀏覽器SessionId消失。
如果客戶端禁用cookie,可以使用url重寫的方法實現會話跟蹤。
session用來表示用戶會話,session對象在服務端維護。
cookie存放在客戶端,可以分為內存cookie和磁盤cookie,超時消失。
隱藏域在頁面中對於用戶是不可見的,在表單中插入的目的是收集和發送消息。
9、cookie
10、session
11、表單域
12、URL重寫
13、Servlet
14、Filter
servlet中的過濾器格式:
<filter>
<filter-name> xxxx</filter-name>
<filter-class> xxxx.aaaa</filter-class>
</filter>
<init-param>(可選)
<parma-name>charset</param-name>
<param-value> UTF-8</param-value>
</init-param>
<filter-mapping>
<filter-name> xxxx</filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>
filter-mapping可映射到一個或者多個servlet或JSP文件,<url-pattern>可映射到任意特征的URL。
15、對象的初始化
16、Error.jsp
17、Properties
Properties實現了Map接口,是線程安全的。(setProperties方法中有synchronized)
18、\ 和 /
19、日志
日志的級別大小關系:ALL<TRACE<DEBUG<INFO<WARN<ERROR<FATAL<OFF
log4j建議只使用四個級別:優先級從高到低:ERROR>WARN>INFO>DEBUG
20、反射(xml、)
反射破壞了原有的訪問修飾符的訪問限制。
21、內聯函數
java中的內聯函數從空間換時間,===》遞歸適宜用內聯(原理是使用方法時不需要再調用)
final關鍵字會告訴編譯器,可以將final函數視為內聯函數,但編譯器最終會權衡性能再做確定。final有助於鎖定方法和提高效率。缺點是占用空間,消耗內存。
22、Volatile
volatile 修飾成員變量被線程訪問時,都強迫線程從共享內存中重讀該成員變量的值。而且,當其值發生變化,強迫線程將變化之后的值寫到共享內存中。故兩個線程總是能看到同一個值。如此一來,一個volatile對象的引用可能為null,(提示該變量的值已經改變,需要從原始內存地址中讀取該值)
使用地方: 1. 中斷服務程序中修改的供其他程序檢測的變量加 volatile
- 多任務環境下各任務間共享的標志應該加volatile
- 存儲器映射的硬件寄存器通常也要加 volatile說明,因為每次讀寫都有不同意義
另外:還要考慮數據的完整性(相關聯的幾個標志讀了一半被打斷重寫)
- 通過關中斷來實現, 2.可以禁止任務調度, 3.依靠良好的硬件設計,
Volatile修飾的作用:
1)可見性:指在一個線程中對該變量的修改會馬上由工作內存(高速緩存、獨享內存)寫會到主內存(共享內存),馬上反應在其它線程讀取中。
2)禁止指令重排序優化:由於編譯器優化,在實際執行中語句的執行順序可能不同,這在單線程執行可保證結果一致,在多線程中可能導致嚴重的問題,volatile可以防止代碼優化。
在JDK1.5之前,volatile不起作用,雙重檢查鎖形式的單例模式無法保證線程安全,??
23、ThreadLocal:線程局部變量
java.lang.ThreadLocal是TLS技術實現。
線程局部變量不能解決靜態變量的存取沖突,故變量仍需同步。可解決多線程中對同一變量的訪問沖突。
24、transient
25、JVM相關(類的加載和執行)
1、JVM的功能:
a.通過ClassLoader尋找和裝載class文件
b.解釋字節碼成為指令並運行,提供class文件運行環境
c.進行運行期間垃圾回收
d.提供與硬件交互的平台
2、垃圾回收:
1)虛擬器線程等待JVM到達安全點之后出現,操作必須在獨立的線程里執行,因為當堆修改無法進行時,線程需要JVM位於安全點。VMThread包括stop-the-world垃圾回收、線程棧dump、線程暫停、線程偏向鎖(basicObjectLock)解除。
2)safePoint安全點可以掛起線程,防止線程無限運行,一般位於循環末尾(防止大循環)、方法返回前、調用方法的call之后、拋出異常的位置。
3)safepoint 只能處理一些正在運行的線程,對於一些sleep()或block()的線程會被添加到safe region區域。標記safe region。當它被喚醒時,應該先檢查GC是否完成操作。
4)GC的時候,所有進入safepoint的線程會在一個Thread.lock鎖阻塞,直到當JVM的GC完成操作,JVM釋放鎖,阻塞的JAVA線程才能運行。
5)GC線程:這些線程支持JVM中不同的垃圾回收活動。
6)對象的回收:對象、數組存放在JVM堆中,分為新生代和老年代。新生代分為三個區,一個Eden、兩個survivor,對象創建之后存在Eden(容量很大的對象可以創建到老年代)。新生代會執行MinorGC,98%的對象會被回收,不被回收的對象轉移(復制算法)到一個survivor中,然后等待下一次MinorGC,GC之后Eden剩下的對象和survivor中的對象都被轉移到另一個servivor中,對象就在兩個survivor中不斷轉換。直到經歷15次MinorGC才能進入老年代(old)。old中會執行FullGC,但比MinorGC的執行頻率要低很多。FullGC一般耗時為MinorGC的22.89倍。新生代一般18M,老年代一般42M。
7)垃圾回收由新生代和年長代協作,稱為分代回收,分別采用復制算法和標記整理算法。
復制算法:兩個區域A和B,初始化對象在A,繼續存活的對象被轉移到另一個區。用在新生代的回收上。新生代分為一個Eden、兩個survivor區。
標記整理算法:一塊區域,對所有的對象進行標記(可達性標記),然后回收不可達對象,因為不是復制轉移算法,所以會出現碎片。整理算法可以將碎片空間進行整理,整理出更大的內存空間存放更大的獨享。
7)對象的回收機制:當前對象是否回收,主要是采用可達性分析,如果不可達,會進行一個F-Queue隊列之中,在finalize方法執行過程中,會進行第二次標記是否可達,選擇自救還是回收。垃圾回收線程在jvm中優先級相當的低。
8)程序開發者只能推薦JVM進行回收,但何時回收,回收哪些不能控制,-->可通過system.gc()來建議gc回收。垃圾回收只是回收不再被使用的JVM內存,與內存是否溢出沒有直接關系。
9)真正宣布一個對象死亡:第一次標記-->調用finalize方法-->第二次gc回收。
10)各版本的垃圾回收器:
單線程收集器,在進行垃圾收集時,必須暫停其他所有的工作線程,直到它搜集結束。
多線程收集器,
jdk1.3 Serial New收集器:針對新生代,單線程收集器(使用復制收集算法)
jdk1.4 Parallel New收集器:並行回收,多線程收集器(新生代和年長代采用不同的算法)。
jdk1.4 Paraller Scavenge:並行,新生代多線程,吞吐量最大化,精確控制吞吐量。 吞吐量=運行用戶代碼/CPU運行時間(用戶代碼+垃圾回收)
jdk1.5 CMS(Concurrent Mark Sweep)目標:最短回收停頓時間。(標記-清除)
jdk1.5 Serial Old老年代版本,它同樣是一個單線程收集器,(使用標記整理算法)
jdk1.6 Parallel Old並行,注重吞吐量以及CPU資源敏感的場合,可以優先考慮Parallel Scavenge+Parallel Old收集器組合。
jdk1.7 G1並行與並發、分代收集、空間整合、可預測的停頓,有意代替GMS。(整體標記整理,局部采用復制)
11)內存泄漏(Memory leak)是指一個不再被使用的對象或者變量還在內存中占用存儲空間,在java語言中引入垃圾回收機制,有GC負責進行回收不再使用的對象,釋放內存。但還是會出現內存泄漏,主要有兩個情況:1)堆中申請的空間沒有釋放,2)對象仍保留連接引用(例如數據庫連接)
12)內存泄漏的原因:如數據庫連接、網絡連接、IO連接,不再使用時如果連接不釋放容易造成內存泄漏。釋放對象時往往沒有刪除響應的監聽器,可能造成內存泄漏。
13)內存溢出(OOM)是指程序在申請內存時沒有足夠的內存供使用,進而導致程序奔潰。內存泄漏最終導致內存溢出。
2、JVM維護了一個數據結構,記錄了所有的線程,所以它可以快速檢查所有線程的狀態。
3、JVM通過控制主內存與每個線程的本地方法內存之間的交互,為java提供內存可見性(保證線程通信)。
4、如果使用jconsole或其他調試器,會看到很多線程在后台運行,主要有JVM線程、觸發main方法的主線程以及主線程創建的其他線程一起運行。
5、JVM有兩種執行方法:解釋型和編譯型(JIT)
在JIT執行方式下,將safepoint的檢查代碼加入到本地代碼,當JVM需要線程進入safepoint時,只需要設置標志位,運行到標志位,如果標志位被設置則進入safepoint。
在解釋型執行下,JVM會設置一個2字節的dispatch tables解釋器,執行過程中會經常檢查這個dispatch tables,當有請求發生時,則讓線程進入safepoint。
6、周期性任務線程:該線程負責定時器事件(也就是中斷),用來調度周期性操作的執行。
7、編譯器線程:這些線程在運行時將字節碼動態編譯成本地平台相關的機器碼。
8、信號分發線程:這個線程接收發送到JVM的信號並調用適應的JVM方法處理。
虛擬機中的線程圖示:
操作系統分配給每一個線程2G的內存,2G = 堆內存+方法區+程序計數器+本地棧+線程棧
一般線程棧有1000-2000棧幀就夠用於遞歸,如果發生內存溢出==沒有多余的內容分配給新對象,可以適當的減少棧的容量,來擴大堆的容量。
26、版本區別(可變參數、枚舉)
JDK1.5版本變化:可變參數、condition鎖、
JAVA支持傳遞同類型的可變參數給一個方法,一個方法只能指定一個位於參數末尾的可變參數;...在類型和參數名之間;以數組形式存在。
JDK1.7版本變化:字符串常量池、
字符串常量池從方法區移到堆中。
新增了多個catch的功能:先小后大
JDK1.8版本變化:
廢棄永久代(Perm Gen)整個常量池從方法區移除,方法區使用元空間(Meta-Space)實現。
接口中的方法可以由static和default修飾。static修飾的方法由接口直接調用,默認修飾符的方法只能由接口的實現類調用,提供了可選功能。
抽象類的訪問權限由Protected變為default。
JDK1.9版本變化:
接口的方法修飾符可以為private
27、數據庫(JDBC、DBMS)
JDBC:JNDI--DataSource---連接池(c3p0\dbcp\Proxool)----DriverManager---connection
oracle的數據庫驅動:oracle.jdbc.driver.OracleDrive
mysql 的數據庫驅動:com.mysql.jdbc.Driver
數據庫連接方式有兩種:
1.建立JDBC--ODBC橋接器(微軟提供)依賴平台,
2.直連純Java數據庫驅動(數據庫廠家提供例如 mysql的mysql-connector-java.jar)
數據庫實現查詢功能:
- 加載JDBC驅動
- 建立並獲取數據庫連接----->通過連接池建立多個連接備用,使用什么連接池用戶自定
- 創建JDBC statements對象--
- 設置SQL語句的傳入參數->用if,else判斷傳入的參數#變量名#占位符 $變量名$非占位符
- 執行SQL語句並獲得查詢結果
- 對結果進行轉換處理並返回
- 釋放相關資源
經過優化之后:
(1) 使用數據庫連接池對連接進行管理
(2) SQL語句統一存放到配置文件中
(3) SQL語句變量和傳入參數的映射以及動態SQL
(4) 動態SQL語句處理
(5) 對數據庫操作結果的映射和結果緩存
(6) SQL語句的重復
驅動的加載方法有:
a、調用方法class.forName
b、通過添加系統的jdbc.drive屬性
c、通過registerDriver方法注冊
DriverManger.getConnection方法返回一個Connection對象,這是加載驅動之后才能進行的。
PreparedStatement和Statement的區別:
創建時:
1) Statement statement = conn.creatStatement();
2) PrepareStatement preStatement = conn.PrepareStatement(sql);
執行時:
1) ResultSet rSet = statement.executeQuery(sql);
2) ResultSet pSet=preStatement.executeQuery();
PreStatement 有預編譯過程,已經綁定sql,之后無論執行什么遍,都不會再去編譯。
而statement不同,如果執行多遍,就需要編譯多遍,所以prestatement效率比較高。
3)安全性:prepareStatement是預編譯的,所以可以有效的防止SQL注入等問題。
4)可讀和維護:后期維護prepareStatement也比較好讀。
JDBC-ODBC方式:
建立JDBC-ODBC橋接器,(使用java.lang中的class類,使用靜態方法forName加載驅動)
創建ODBC數據源,
建立與ODBC的連接(可能異常)
DBMS:數據庫管理系統,事務具有持久性、一致性、原子性、隔離性。
持久性實現恢復管理子系統,一致性實現並發控制子系統,
原子性實現完整子系統,隔離性實現安全控制管理子系統。
一般關系數據模型和對象數據模型之間有以下對應關系:表對應類、記錄對應對象、字段對應屬性,ORMapping只是規定了結構和集的映射。
28、Web容器
web容器給處於其中的應用程序組件(JSP、Servlet)提供一個環境,使JSP、Servlet直接依靠容器中的環境變量交互,不用關注其他系統問題,主要由WEB服務器實現。
J2EE中的WEB容器主要有:
EJB容器(Enterprise java bean)提供給運行在其中的組件EJB各種管理功能,滿足J2EE的組件被高效率的管理,並且可以通過現成的接口獲得系統級別服務,例如:郵件服務,事務管理
JNDI(Java Naming&Directory Interface):Java命名目錄服務。功能:提供一個目錄級,讓其它各地的應用程序在其上留下自己的索引,從而滿足快速查找和定位分布式應用程序的功能。
JMS(Java Message Service):主要實現各個應用程序之間的通訊,包括點對點和廣播。
JTA(JAVA Transcation API):Java事務服務,提供各種分布式事務服務,應用程序只需要調用其提供的接口。
JAF(Java Action FrameWork):Java安全認證框架,讓開發者通過各種部署和自定義實現自己的個性安全控制。
RMI/IIOP(Remote Method Invocation/internet對象請求中介協議):主要用於遠程調用服務。異構系統通過一定的規范才可實現調用。RMI是Java特有的。(Stub和Skeleton)
JMX(Java Management Extensions) Java 管理擴展是一個為應用程序、設備、系統等植入管理功能的框架,可以跨越一系列異構操作系統平台、系統體系結構和網絡傳輸協議,靈活的開發無縫集成系統、網絡和服務管理應用。1.3之后開始支持。
Swing提供了3種頂層容器類:JFrame、JDialog、JApplet。
Maven 的核心功能就是合理敘述項目間的依賴關系,通過pom.xml配置jar包信息。一般使用三種方式:本地倉庫、第三方倉庫、中央倉庫。
29、常用API(String、集合、Thread)
30、JSP
1、JSP的九大內置對象及四個作用域
request 請求對象 類型:javax.servlet.servletRequest 作用域: Request
response 響應對象 javax.servlet.servletResponse Page
pageContext 頁面上下文對象 javax.servlet.jsp.PageContext Page
session 會話對象 javax.servlet.http.HttpSession Session
application 應用程序對象 javax.servlet.servletContext Application
out 輸出對象 javax.servlet.jsp.JSPWriter Page
config 配置對象 javax.servlet.ServletConfig Page
page 頁面對象 javax.lang.Object Page
exception 例外對象 javax.lang.Throwable Page
JSP的四大域:
Page作用域代表當前頁面有效,一旦JSP頁面結束,page中的數據將消失。
Request 作用域是請求過程,從JSP頁面發出請求,到頁面跳轉轉發,服務器servlet處理,發回響應。在forward轉發的JSP頁面都可以使用request中的數據。
Session作用域是會話,從打開瀏覽器就會創建一個session對象存儲在瀏覽器,在瀏覽器關閉之前都可以使用session(用戶獨享)。
Application 作用域是應用,從開啟一個應用到應用結束,都可以使用Application(在服務器的運行過程中都可以使用,可以說是所有用戶共用)
九大內置對象:
response的作用:
1.構建響應信息: 設置http頭標、返回數據類型、
方式一:response.setHeader("Content-type","test/html;charset=utf-8");
方式二:response.setContentType("text/html;charset=utf-8");
2.構建響應實體: 輸出返回數據
方式一:response.getOutputStream().write("xxx".getBytes());string轉成 字節數組
這是一個字節流,是什么字節輸出什么字節,而瀏覽器默認用平台字節碼打開服務器發送的數據,如果服務器端使用了非平台碼去輸出字符的字節數據就需要明確的指定瀏覽器編碼時所用的碼表,以防止亂碼問題,
方式二:response.getWriter().write("xxx")
這是一個字符流,response會將此字符進行轉碼操作后輸出到瀏覽器,這個過程默認使用ISO8859-1碼表,而ISO8859-1中沒有中文,於是轉碼過程中用?代替了中文,導致亂碼問題。可以指定response在轉碼過程中使用的目標碼表,防止亂碼。
response.addHeader("Content-type","text/html;charset=utf-8")/response.setContentType("text/html;charset=utf-8");指定轉碼過程使用的碼表。
PageContext(頁面上下文)可對頁面JSP中所有對象及名字空間訪問頁面功能集大成者。
context.getParameter()獲取POST/GET傳遞的參數(一般jsp到servlet傳值)
context.getInitParameter()獲取Tomcat的server.xml中Context的初始化參數
context.getAttribute()獲取對象容器中的數據值===>用於頁面之間傳值(servlet到jsp傳值)
context.getRequestDispatcher()是請求轉發
exception 代表JSP文件運行時所產生的例外對象,此對象不能在一般JSP中使用,而只能在有此標簽標示<% page isErrorPage = “true” %> 的JSP文件中使用。
當isErrorPage = “false”時,用errorPage = “error.jsp”。(isErrorPage默認為false)。
當isErrorPage = “true”時,頁面會使用Exception。在當前頁面使用異常處理。所以error.jsp頁面一定要有isErrorPage屬性且值為true。
JSP的EL表達式
JSP中的EL表達式作用:
1) 獲取數據:
2) 執行運算
3) 獲取web開發常用對象
4) 調用java方法
<% expression %> 語句塊(腳本) <% = expression %> 表達式
<% !變量.方法 %> 聲明 <%!-- xxxxxx --> 注釋
WEB容器
web容器在啟動時為每個web應用創建一個ServletContext對象,ServletConfig對象維護了ServletContext的引用,開發人員在編寫servlet時,可通過ServletConfig.getServletContext方法獲取ServletContext方法ServletContext對象。所有Servlet共享一個ServletContext,因此Servlet對象可通過其完成通訊,也稱為context域對象。
1) 在InitServlet的service方法中利用ServletContext對象存入需要共享的數據。
ServletContext context = this.getServletContext();
context.setAttribute(“name”,”haha”);
在其他servlet中可獲得數據:
ServletContext context = this.getServletContext();
context.getAttribute(“name”);
2) 獲取WEB應用的初始化參數,在DemoServlet的doPost方法中測試獲取初始化參數:
ServletContext context = this.getServletContext();
String url = context.getInitAttribute(“url”);
31、事件處理模型
Java提供的事件處理模型是一種人機交互模型,有三個基本要素。
1) 事件源:事件發生的場所,指各個組件,如按鈕。
2) 事件: 事件封裝了組件上發生的事件,比如按鈕單擊、按鈕松開等。
3) 事件監聽器:負責監聽事件源上發生的特定類型的事件,當事件到來時,還必須負責處理響應的事件。
32、java特點
一處編寫,到處運行。
Java並不完全是編譯型語言,編譯的字節碼文件運行時是解釋執行的,
Java和C++的類也不都是完全靜態綁定的,java的父子類調用==C++的虛函數。
33、多線程(thread、runnable、collable、condition)
1、守護線程(daemon):通過調用void setDaemon(boolean on)方法將自己設置成一個守護線程。thread.setDaemon(true); 當所有的用戶線程執行結束后,即使守護線程的run()方法還有未執行語句,也會立刻結束線程。
2、從JDK1.5開始,Java提供了三種方式來創建線程:
繼承Thread類創建多線程,重寫run()方法作為線程執行體。(不能再繼承其他類\每一條線程都是Thread子類的實例共享數據復雜)
實現Runnable接口來創建線程,重寫run()方法作為線程執行體。Thread(Runnable in);
實現Callable接口創建線程,重寫run()方法作為線程執行體。實現Callable可返回結果,可拋出異常,通過futureTask.get(),方法獲取結果,如果沒有結果返回,可能會阻塞主線程。
3、線程知識
t.start(); 方法啟動一個線程,使其處於就緒狀態,得到CPU就執行,而調用run()相當於普通的方法調用。start()方法將“新建”狀態下的線程加入“就緒”隊列中等待CPU,run()方法屬於Thread(),沒有內容,需要重寫。調用start()會默認調用run()。
**************************
***********************
******此處 缺一個 線程狀態轉換圖
****
(1)對象與線程之間完全解耦or弱解耦(用構造方法創建線程實現聯系)
(2)線程同步用sychronized修飾方法
(3)協調同步用wait()等待其他線程完成工作(釋放CPU資源)
(4)線程聯合,A聯合B,A立刻停止,讓B先執行
(5)守護線程做一些不重要的工作,一旦所有線程停止工作,守護線程立刻停止
4、常用方法:start()、run()、sleep(ms)、isAlive()===>false true false
wait()、sleep()都需要try/catch包裹,或是拋出InterruptedException(檢查異常)。
sychronized(同步鎖)的目標與wait()方法的目標不一致,會拋出IllegalMonitorSateException,不過InterruptExcprion會先出現。wait()和notify()方法必須采用當前鎖調用,必須采用synchronized中的對象。
wait()、notify()、notifyAll()都是Object類中的final方法,被所有類繼承且不允許重寫,不可以在非同步方法中出現。
Thread.currentThread() 返回正在實行的線程名稱
Thread.interrupt() 用於將當前線程的中斷標志位設置為true,如果是wait、sleep、join造成的阻塞,會重新將標志位設置為false,拋出interruptedException異常。如果是IO阻塞會拋出異常,如果是輪詢,直接返回。如果是非阻塞的線程,進入阻塞會按照阻塞來處理,非阻塞中斷標志位為true的線程遇到wait、join、sleep,直接拋出interruptException,中斷標記被清除,設置中斷標志位為false。
CyclicBarrier(柵欄)讓一組線程等待一個或一些線程,countDownLatch(閉鎖)讓一組線程等待某個事件。
CopyOnWriterArrayList適合使用在讀操作遠遠大於寫操作的場景中,比如緩存。
ReadWriteLock當寫操作時,其他線程無法讀取或寫入數據,而當讀操作時,其他線程無法寫入數據,但可以讀,適用於讀取遠遠大於寫入的場景。
Thread.stop()已經棄用。
Thread.suspend()和resume()方法:suspend()使線程進入阻塞狀態,並不會自恢復,調用其resume()方法才能使其進入就緒隊列。
線程安全問題出現的情況:
1,多個線程使用共用數據時
2,操作共享數據的線程代碼
當一個線程在執行操作共享數據的多條代碼的過程中,其他線程參與了運算。就會導致線程的安全問題。
解決思路:
就是將多條操作共享數據的線程封裝起來,在有線程在執行這些代碼的時候,其他線程是不可以參與運算的。
Synchronized :同步代碼塊:
Synchronize(對象)
{
需要被同步的代碼;
}
同步的好處和弊端:
解決了線程的安全問題。
效率有一點點低。因為同步外的線程都會判斷同步鎖。
同步的使用前提:多線程才使用同步,多線程使用的為同一個鎖才使用。
同步代碼塊:同步代碼塊的鎖是任意的。
同步函數:主線程開啟線程后,占用CPU,執行完語句。同步函數使用的鎖是當前的對象 this。
4、同步監視器:
任何線程進入同步方法,同步代碼塊之前,必須先獲得同步方法,同步代碼塊對應的同步監視器。對於同步代碼塊,程序必須顯式的為它指定同步監視器。
對於非靜態同步方法,該方法的同步監視器是this--調用該方法的對象,
對於靜態的同步方法,該方法的同步監視器是類。
Static Synchronized 是一個類的共用監視器,synchronized 是針對擁有同步方法的類 而存在的當前實例的監視器。
1、線程中鎖:conditon 線程的阻塞隊使用的是 condition互斥鎖。
Condition是在JDK1.5中才出現,Condition的作用是對鎖進行更精確的控制,擁有await()、signal()、signalAll()、用來替代傳統的Object()的wait()、notify()、notifyAll()。不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步鎖"(synchronized關鍵字)捆綁使用的;而Condition是需要與"互斥鎖"/"共享鎖"捆綁使用的。調用await()和signal()都必須在lock.lock()和lock.unlock()之間有效。
2、線程調度分為協同調度和搶占性調度,Java使用的是搶占性調度,每個線程由操作系統分配執行時間。協同式調度是指調度線程由線程自身確定。
3、可能會拋出InterruptedException的方法:java.lang.Object類的wait方法,
java.lang.Thread類的sleep方法,
java.lang.Thread的join方法。
Thread.suspend容易造成死鎖,已過時,被打斷不會拋出InterruptedException()。
4、線程結束的三個原因:
1)run方法執行完成,線程正常結束。
2)線程拋出一個未捕獲的Exception或Error
3)調用該線程的stop方法結束線程(容易死鎖)
4)thread-clean-pop 拋出一個例外,線程終止,也可以通過其他線程調用thread-cancel()來終止另一個線程。
34、良好的代碼習慣
1、面向接口編程:List myList = new ArrayList(); === 接口名 xxx = new 接口實現類
Map map = new HashMap();
(1)程序規范化設計 (2)團隊協同開發 (3)轉換為組件 (4)代碼復用
2、Java中路徑用 “/” 才是正確的,如果使用了 “\”表示路徑,需要轉義。”\”也是轉義符。
35、Java的三大注解( 由虛擬器控制給出注解,提示開發人員注意編碼規則 )
(1)@SuppressWarnings(“deprecation”); ==>屏蔽相應的警告,(一般在方法上標注)
(2)@Override; 指定被注解的方法需要覆寫超類的方法(1.5實現接口方法不能寫,6.0可寫)
(3)@Deprecated;表明程序調用一個廢棄元素(方法),編譯器應該顯示警告(不能被使用)
元注解(Meta-Annotations,Java注解類型):Target、Retention、Documented、inherited。
@Target:注解表明注解類型適用於哪種目標元素,@Target(ElementType TYPE)適用任何類的元素包括:元素字段、方法、參數、構造函數、局部變量、類型本身。
36、內聯函數
37、存根類(Stub)
Stub是一個類,它實現了一個接口。繼承該類就可以使用(間接)接口的方法,(不用全實現)。RMI采用Stub和Skeletons來進行遠程對象的通訊,Stub充當客戶端代理(運行在本地虛擬機),遠程對象的調用實際上是通過調用該對象的客戶端代理Stub來完成的。
每一個遠程對象都包含一個代理對象Stub,當運行在本地虛擬機上的程序想調用遠程Java虛擬機上的方法時,1)在本地創建該對象的代理對象Stub,然后調用代理對象上的方法,在遠程有一個skeleton對象與Stub呼應,接受來自Stub對象的調用。(運行時動態鏈接??)
38、擴展方法
擴展方法只能訪問所擴展類的public成員。
39、數組(數組復制)
(1)System.arrayCopy用本地方法(C語言)實現==>使用java間接操作硬件
(2)clone() 定義:protected native Object clone() throws CloneNotSupportedException{}
(3)arrays.CopyOf 調用了system.arraycopy 方法實現
(4)用for循環實現,效率最低
40、設計模式:
單例:多線程下的單例
餓漢式單例在單例類被加載時候,就實例化一個對象交給自己的引用;而懶漢式在調用取得實例方法的時候才會實例化對象。
chinese.getInstance(); 每次獲取的都是同一個對象。
41、JavaWeb項目:
1.測試
2.梳理
42、SSM:Spring + SpringMVC + MyBatis
- Spring 2.struts 3.springMVC 4. MyBatis 5.Hibernate
1、Spring是一個開源的Java/ Java EE全功能棧應用程序框架。輕量級的控制反轉(IoC)和面向切面(AOP)的容器框架。可通過AOP和log4j實現自定義日志系統。
①、基於JavaBeans 的采用控制反轉的配置管理,使得應用程序的組建更加快捷簡易。
②、一個可用於從applet到JavaEE不同運行環境的核心Bean工廠。
Spring:
依賴注入是一種思想,或者說是一種設計模式,在java中通過反射機制實現,與具體框架無關,依賴注入(DI)有三種方式:接口注入、Setter注入、構造方法注入。
Spring: 基於xml文件配置
<!--配置事務管理器-->
<Property name=”transactionManger”>
<!--配置事務屬性>
<Property name=”transactionAttributes”>
<Prosp>
聲明式事務管理建立在AOP上,其本質是對方法前后進行攔截。在目標方法開始之前創建或者加入一個事務,在執行完目標方法之后根據執行情況提交或者回滾事務。
優點:不需要通過編程的方式管理事務,只需要在配置文件中做相關的事務規則聲明(或通過@Transactional注解方式將事務應用到邏輯中)。
3、SpringMVC:分離了控制器、模型對象、分派器以及程序對象的角色。易於其他的view框架,采用IoC便於測試。MVC作為WEB項目開發的核心環節,C(控制器)、V(視圖、用戶客戶端)、M(模型、業務)。
MVC的功能實現 圖示:
DispatcherServlet 作為SpringMVC的前端控制器,負責接收用戶請求並根據請求返回視圖給用戶,業務操作在service層。
4、MyBatis
MyBatis:是一個基於Java的持久層框架,支持定制化SQL、存儲過程以及高級映射。避免了幾乎所有的JDBC代碼和手動設置參數以及獲取結果集。MyBatis可以使用簡單的XMl或注解來配置和映射原生信息,將接口和Java的POJOs(普通Java對象)映射成數據庫中的記錄。
MyBatis的功能:
5、Hibernate
Hibernate使用了Java反射機制實現透明性。
Hibernate鼓勵使用雙向一對多關聯,不使用單向一對多關聯。
優化Hibernate 的七大舉措:
1)盡量使用many--to--one,避免使用單向one--to--many
2)靈活使用單向one--to--one
3)多對一代替一對一
4)配置對象緩存,不使用集合緩存
5)一對多使用Bag,多對一使用Set
6)繼承使用顯式多態HQL: from Object polymorphism=”exlicit” 避免查處所有對象
7)消除大表,使用二級緩存
Hibernate 中的Get和load的區別:
1、get()采用立即加載方式,而load()采用延遲加載。
get()方法,立即向數據庫發出查詢語句,而load()方法返回的是一個代理(只有id屬性)只有真正使用屬性時,才會執行查詢。
1、如果數據庫沒有響應的記錄,get()方法會返回null,而load()方法會拋出異常ObjectNotFoundException。
hibernate2 和 Hibernate3 的區別:
Hibernate2延遲加載實現:a)實體對象,b)集合(Collection)
Hibernate3提供了屬性的延遲加載功能,只有真正使用時,才執行sql查詢,節省了服務器的內存開銷,從而提高了服務器的性能,它是一個基於JDBC的主流持久層框架,是一個優秀的ORM實現,它很大程度簡化了DAO層的編碼工作。