Java面試題:面試中遇到的問題總結
面試總結
jQuery中的$是什麼意思及 $. 和 $().的區別
$就是jQuery的別稱
而jQuery就是jQuery庫提供的一個函式.(好像也不僅僅只是函式, 因為還有 $.ajax(options) 這樣的使用,等同 jQuery.ajax(options))
這個函式的作用是根據 () 裡的引數進行查詢和選擇html文件中的元素, 函式作用之一就是GetElementByID的代替,但()內不僅可以是ID,還可以是各類選擇器
比如:
$(document)就是 選取整個文件物件
那是不是隻可以用$來代替,不是。為了防止命名衝突,jQuery庫提供了另外的機制來給jQuery函式起另外的別名。
下面看下在jquery中,用 $. 和 $().有什麼區別,它們分別的含義是什麼?
$就是jquery物件,$()就是jQuery(),在裡面可以傳引數,作用就是獲取元素
在jQuery中,最頻繁使用的符號“$”。$提供了各種各樣豐富的功能,
1.包括作為選擇器選擇頁面中的一個或是一類元素
2.作為功能函式的字首
javascript沒有提供類似trim()的功能,而引入jQuery後,便可以直接使用trim()函式,例如$.trim(sString);
以上程式碼相當於:jQuery.trim(sString);即trim()函式時jQuery物件的一個方法。
3.window.onload的完善
4.建立頁面的DOM節點
如下例子
$(".div1") 表示獲取類名為div1的元素,例如獲取<div class="div1"></div>
$(".div1").onclick表示類名為div1的div點選事件
jquery中$.,例如$.post(),$.get(),$.ajax()等這些都是jquery這個物件的方法
"=="和equals方法究竟有什麼區別?
1)==是用於比較兩個物件的記憶體地址值(引用值)是否相等;equals()方法是用於比較兩個物件的內容是否一致。
2)對於非字串變數來說,==和equals方法的作用是相同的都是用來比較其物件在堆記憶體中的首地址,即用來比較兩個引用變數是否指向同一個物件。
3)如果是基本型別比較,只能用==來比較,不能用equals。
4)對於基本型別的包裝型別,比如Boolean,Character,Byte,Shot,Integer,Long,Float,Double等的引用變數,==是比較地址的,equals是比較內容的。
5)字串的比較基本上都是使用equals方法
AJAX中根據async的值不同分為同步(async = false)和非同步(async = true)兩種執行方式;
普通B/S模式(同步)AJAX技術(非同步)
同步:提交請求->等待伺服器處理->處理完畢返回 這個期間客戶端瀏覽器不能幹任何事
非同步: 請求通過事件觸發->伺服器處理(這是瀏覽器仍然可以作其他事情)->處理完畢
一.什麼是同步請求:(false)
同步請求即是當前發出請求後,瀏覽器什麼都不能做,必須得等到請求完成返回資料之後,才會執行後續的程式碼,相當於是排隊,前一個人辦理完自己的事務,下一個人才能接著辦。也就是說,當JS程式碼載入到當前AJAX的時候會把頁面裡所有的程式碼停止載入,頁面處於一個假死狀態,當這個AJAX執行完畢後才會繼續執行其他程式碼頁面解除假死狀態。
二.什麼是非同步請求:(true)
非同步請求就當發出請求的同時,瀏覽器可以繼續做任何事,Ajax傳送請求並不會影響頁面的載入與使用者的操作,相當於是在兩條線上,各走各的,互不影響。
一般預設值為true,非同步。非同步請求可以完全不影響使用者的體驗效果,無論請求的時間長或者短,使用者都在專心的操作頁面的其他內容,並不會有等待的感覺。
有人說:既然非同步這麼好,那全部都用非同步好了,同步存在還有什麼意義?
那麼,同步適用於一些什麼情況呢?
我們可以想一下,同步是一步一步來操作,等待請求返回的資料,再執行下一步,那麼一定會有一些情況,只有這一步執行完,拿到資料,通過獲取到這一步的資料來執行下一步的操作。這是非同步沒有辦法實現的,因此同步的存在一定有他存在的道理。
多執行緒有幾種實現方法?同步有幾種實現方法?
多執行緒有兩種實現方法,分別是繼承Thread類與實現Runnable介面
同步的實現方面有兩種,分別是synchronized,wait與notify
wait():使一個執行緒處於等待狀態,並且釋放所持有的物件的lock。
sleep():使一個正在執行的執行緒處於睡眠狀態,是一個靜態方法,呼叫此方法要捕捉InterruptedException異常。
notify():喚醒一個處於等待狀態的執行緒,注意的是在呼叫此方法的時候,並不能確切的喚醒某一個等待狀態的執行緒,而是由JVM確定喚醒哪個執行緒,而且不是按優先順序。
Allnotity():喚醒所有處入等待狀態的執行緒,注意並不是給所有喚醒執行緒一個物件的鎖,而是讓它們競爭。
HashMap和Hashtable的區別
hashtable是執行緒安全的,即hashtable的方法都提供了同步機制;
hashmap不是執行緒安全的,即不提供同步機制 ;
hashtable不允許插入空值,hashmap允許!
HashMap是非執行緒安全的(非同步的)。那麼怎麼才能讓HashMap變成執行緒安全的呢?
我認為主要可以通過以下三種方法來實現:
1.替換成Hashtable,Hashtable通過對整個表上鎖實現執行緒安全,因此效率比較低
2.使用Collections類的synchronizedMap方法包裝一下。方法如下:
3.使用ConcurrentHashMap,它使用分段鎖來保證執行緒安全
//Hashtable
Map<String, String> hashtable = new Hashtable<>();
//synchronizedMap
Map<String, String> synchronizedHashMap = Collections.synchronizedMap(new HashMap<String, String>());
//ConcurrentHashMap
Map<String, String> concurrentHashMap = new ConcurrentHashMap<>();
通過前兩種方式獲得的執行緒安全的HashMap在讀寫資料的時候會對整個容器上鎖,而ConcurrentHashMap並不需要對整個容器上鎖,它只需要鎖住要修改的部分就行了
List、Map、Set三個介面,存取元素時,各有什麼特點?
list集合
有序 不唯一(可重複)
子類 ArrayList LinkedList 最常用 ArrayList
ArrayList 底層就是陣列
List集合在collection介面基礎上增強很多功能
ArrayList 與 LinkedList 區別:
實現原理不同 ArrayList 陣列 LinkedList 連結串列
ArrayList 查詢快 增刪改慢
LinkedList 查詢慢 增刪改快
Set集合
無序 唯一(不可重複)
首先,List與Set具有相似性,它們都是單列元素的集合,所以,它們有一個功共同的父介面,叫Collection。Set裡面不允許有重複的元素,所謂重複,即不能有兩個相等(注意,不是僅僅是相同)的物件 ,
List表示有先後順序的集合, 。
Map與List和Set不同,它是雙列的集合,其中有put方法,定義如下:put(obj key,obj value),每次儲存時,要儲存一對key/value,不能儲存重複的key,這個重複的規則也是按equals比較相等。取則可以根據key獲得相應的value
List 以特定次序來持有元素,可有重複元素。Set 無法擁有重複元素,內部排序。Map 儲存key-value值,value可多值。
HashSet按照hashcode值的某種運算方式進行儲存,而不是直接按hashCode值的大小進行儲存
遍歷map的4種方式:
普遍使用 二次取值
for(String key : map.keySet()){
System.out.println("key : " + key + "\t value : "+ map.get(key));
}
通過Map.entrySet 和Iterator 遍歷key 和value
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, String> entry = it.next();
System.out.println("key : " + entry.getKey() + "\t value : "+ entry.getValue());
}
推薦使用 尤其容量大時
for(Map.Entry<String, String> entry : map.entrySet()){
System.out.println("key : " + entry.getKey() + "\t value : "+ entry.getValue());
}
通過map.value 遍歷value 但不能遍歷key
for(String str : map.values()){System.out.println(str);}
Collections 與 collection的區別:
Collections 是容器的操作類 類似於 Arrays
Collection 是介面 定義規範方法的
去掉一個Vector、ArrayList集合中重複的元素
ArrayList list=new ArrayList();
String a="aaa";
list.add(a);
list.remove(a);//根據物件刪除
- 按下標刪除 如:
list.remove(0),
list.remove(list.size() -1);
2.按元素刪除 如:
list.remove(list.get(0)) 刪除第一個元素
list.remove(list.get(list.size()-1)) 刪除最後一個元素
或者下面方法把Vector 換成ArrayList即可
Vector newVector = new Vector();
For (int i=0;i<vector.size();i++)
{
Object obj = vector.get(i);
if(!newVector.contains(obj);
newVector.add(obj);
}
還有一種簡單的方式,HashSet set = new HashSet(vector);
遞迴演算法
public class DiguiHe{
public static void main(String[] args) {
System.out.println("遞迴1-100和:"+dghe(5));
System.out.println("遞迴1-100和:"+fdghe(5));
}
/**
* 遞迴1-100和
*/
private static int dghe(int i) {
/**
* 這裡以5為例:
* 5+dghe(4)=5+4+dghe(3)=5+4+3+dghe(2)+5+4+3+2+dghe(1)=5+4+3+2+1
* 當dghe(1)走 return 1;程式結束了
*/
if(i == 1){
return 1;
}else{
return i+dghe(i-1);
}
}
/**
* 非遞迴1-100和
*/
private static int fdghe(int i) {
int sum = 0;
int j = 1;
while(j<=i){
sum+=j;
j++;
}
return sum;
}
}
遞迴10的階乘
public class DiguiChen{
public static void main(String[] args) {
System.out.println("遞迴階乘:"+dgjc(10));
System.out.println("非遞迴階乘:"+fdgjc(10));
}
/**
* 遞迴階乘
*/
private static int dgjc(int i) {
//這裡舉例5的階乘,10的階乘同理:
//5*dgjc(4)=5*4*dgjc(3)=5*4*3*dgjc(2)=5*4*3*2*dgjc(1)=5*4*3*2*1=120
if(i == 1){
return 1;
}else{
return i*dgjc(i-1);
}
}
/**
* 非遞迴階乘
*/
private static int fdgjc(int i) {
int sum = 1;
while(i>0){
sum*=i;
i--;
}
return sum;
}
}
說出一些資料庫優化方面的經驗?
使用索引
少用SELECT*
對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
不要把SQL語句寫得太長,太過冗餘
使用NOT NULL
where子句優化避免在 where 子句中使用 or 來連線
應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
應儘量避免在 where 子句中對欄位進行 null 值判斷
Mysql分頁查詢關鍵字: limit
Oracle分頁查詢關鍵字:runnum
獲得兩個日期之間的天數
首先把獲取的字串日期轉換成Date型別(從前臺頁面獲取的是字串型別的日期 a,b):
Date a1 = new SimpleDateFormat("yyyy-MM-dd").parse(a);
Date b1 = new SimpleDateFormat("yyyy-MM-dd").parse(b);
//獲取相減後天數
long day = (a1.getTime()-b1.getTime())/(24*60*60*1000);
getTime 方法返回一個整數值,這個整數代表了從 1970 年 1 月 1 日開始計算到 Date 物件中的時間之間的毫秒數是long型別,如果要顯示日期,需要進行格式化,比如使用 SimpleDateFormat
@Controller 用於標記在一個類上,使用它標記的類就是一個SpringMVC Controller 物件
@RequestMapping是一個用來處理請求地址對映的註解,可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。
package com.cqvie.handler;
import org.springframework.stereotype.Controller;
@Controller
public class HelloWorld {
@RequestMapping("/helloworld")
public String sayHello() {
System.out.println("Hello World!");
return "success";
}
}
@RequestParam:用於獲取傳入引數的值
@RequestMapping("/requestParams1.do")
public String requestParams1(@RequestParam(required = false) String name){
System.out.println("name = "+name);
return "index";
}
@Resource和@Autowired都是做bean的注入時使用
@Autowired顧名思義,就是自動裝配,其作用是為了消除程式碼Java程式碼裡面的getter/setter與bean屬性中的property。當Spring發現@Autowired註解時,將自動在程式碼上下文中找到和其匹配(預設是型別匹配)的Bean,並自動注入到相應的地方去。當Spring找不到bean時會丟擲異常,將@Autowired註解的required屬性設定為false 不會丟擲異常,會顯示null
當有多個bean對應時,Spring因為不能判定應該使用哪個bean同樣會丟擲異常,此時使用@Qualifier("class-name")註解,即可指定bean
public class HelloWorld{
@Autowired
@Qualifier("userDao")
private UserDao userDao;
}
public class HelloWorld{
// 下面兩種@Resource只要使用一種即可
@Resource(name="userDao")
private UserDao userDao; // 用於欄位上
@Resource(name="userDao")
public void setUserDao(UserDao userDao) { // 用於屬性的setter方法上
this.userDao = userDao;
}
}
@responseBody註解的作用是將controller的方法返回的物件通過適當的轉換器轉換為指定的格式之後,寫入到response物件的body區,通常用來返回JSON資料或者是XML資料。
在使用@RequestMapping後,返回值通常解析為跳轉路徑。加上@responsebody後,返回結果直接寫入HTTP response body中,不會被解析為跳轉路徑。比如非同步請求,希望響應的結果是json資料,那麼加上@responsebody後,就會直接返回json資料。
@ModelAttribute:用於把引數儲存到model中,可以註解方法或引數,註解在方法上的時候,該方法將在處理器方法執行之前執行,然後把返回的物件存放在 session(前提時要有@SessionAttributes註解) 或模型屬性中
@SessionAttributes預設情況下Spring MVC將模型中的資料儲存到request域中。當一個請求結束後,資料就失效了。如果要跨頁面使用。那麼需要使用到session。而@SessionAttributes註解就可以使得模型中的資料儲存一份到session域中。配合@ModelAttribute("user")使用的時候,會將對應的名稱的model值存到session中
@Controller
@RequestMapping("/test")
@SessionAttributes(value = {"user","test1"})
public class LoginController{
@ModelAttribute("user")
public UserEntity getUser(){
UserEntity userEntityr = new UserEntity();
userEntityr.setUsername("asdf");
return userEntityr;
}
@RequestMapping("/modelTest.do")
public String getUsers(@ModelAttribute("user") UserEntity user ,HttpSession session){
System.out.println(user.getUsername());
System.out.println(session.getAttribute("user"));
return "/index";
}
}
啟動Tomcat
./startup.sh
Tomcat關閉命令
./shutdown.sh
檢視Tomcat是否以關閉
ps -ef|grep java
殺死Tomcat程序
kill -9 7010
檢視tomcat日誌
先切換到:cd usr/local/tomcat7/logs
tail -f catalina.out
按ctrl+c即可結束檢視
cp 複製 mv 剪下、重新命名 rm 刪除
ls 檢視目錄內容 ll檢視詳細資訊 cd .. 切換到上級目錄
mkdir 建立目錄 tab 自動補全 cat 檢視檔案內容
ping命令 clear 清除 kill 殺死程序 ifconfig 檢視或配置網絡卡資訊
cat命令主要用來檢視檔案內容,建立檔案,檔案合併,追加檔案內容等功能 例如:cat aa.txt
top命令是Linux下常用的效能分析工具,能夠實時顯示系統中各個程序的資源佔用狀況,類似於Windows的工作管理員
ps與grep常用組合用法,查詢特定程序
命令:ps -ef | grep yushan
more 檢視檔案內容,分頁顯示,按空格翻頁
more和less一般用於顯示檔案內容超過一屏的內容,並且提供翻頁的功能。more比cat強大,提供分頁顯示的功能,less比more更強大,提供翻頁,跳轉,查詢等命令。而且more和less都支援:用空格顯示下一頁,按鍵b顯示上一頁
建立物件的方法:使用New關鍵字、使用Class類的newInstance方法、使用Constructor類的newInstance方法、使用Clone方法、使用反序列化。
1.使用new關鍵字:這是我們最常見的也是最簡單的建立物件的方式,通過這種方式我們還可以呼叫任意的夠贊函式(無參的和有參的)。比如:Student student = new Student();
2.使用Class類的newInstance方法:我們也可以使用Class類的newInstance方法建立物件,這個newInstance方法呼叫無參的構造器建立物件,
如:Student student2 = (Student)Class.forName("根路徑.Student").newInstance();
或者:Student stu = Student.class.newInstance();
3.使用Constructor類的newInstance方法:本方法和Class類的newInstance方法很像,java.lang.relect.Constructor類裡也有一個newInstance方法可以建立物件。我們可以通過這個newInstance方法呼叫有引數的和私有的建構函式。
如:Constructor<Student> constructor = Student.class.getInstance(); Student stu = constructor.newInstance();
這兩種newInstance的方法就是大家所說的反射,事實上Class的newInstance方法內部呼叫Constructor的newInstance方法。這也是眾多框架Spring、Hibernate、Struts等使用後者的原因。
4.使用Clone的方法:無論何時我們呼叫一個物件的clone方法,JVM就會建立一個新的物件,將前面的物件的內容全部拷貝進去,用clone方法建立物件並不會呼叫任何建構函式。要使用clone方法,我們必須先實現Cloneable介面並實現其定義的clone方法。
如:Student stu2 = <Student>stu.clone();這也是原型模式的應用。
5.使用反序列化:當我們序列化和反序列化一個物件,JVM會給我們建立一個單獨的物件,在反序列化時,JVM建立物件並不會呼叫任何建構函式。為了反序列化一個物件,我們需要讓我們的類實現Serializable介面。
如:ObjectInputStream in = new ObjectInputStream (new FileInputStream("data.obj")); Student stu3 = (Student)in.readObject();
Redis本質上是一個Key-Value型別的記憶體資料庫,很像memcached,整個資料庫統統載入在記憶體當中進行操作,定期通過非同步操作把資料庫資料flush到硬碟上進行儲存。因為是純記憶體操作,Redis的效能非常出色,每秒可以處理超過 10萬次讀寫操作,是已知效能最快的Key-Value DB。
Redis支援的資料型別
Redis通過Key-Value的單值不同型別來區分, 以下是支援的型別:
Strings Lists Sets 求交集、並集 Sorted Set hashes
字串String、字典Hash、列表List、集合Set、有序集合SortedSet
為什麼redis需要把所有資料放到記憶體中?
Redis為了達到最快的讀寫速度將資料都讀到記憶體中,並通過非同步的方式將資料寫入磁碟。所以redis具有快速和資料持久化的特徵。如果不將資料放在記憶體中,磁碟I/O速度為嚴重影響redis的效能。在記憶體越來越便宜的今天,redis將會越來越受歡迎。
如果設定了最大使用的記憶體,則資料已有記錄數達到記憶體限值後不能繼續插入新值。
ehcache與redis區別
ehcache直接在jvm虛擬機器中快取,速度快,效率高;但是快取共享麻煩,叢集分散式應用不方便。
redis是通過socket訪問到快取服務,效率比ecache低,比資料庫要快很多,處理叢集和分散式快取方便,有成熟的方案。
如果是單個應用或者對快取訪問要求很高的應用,用ehcache。
如果是大型系統,存在快取共享、分散式部署、快取內容很大的,建議用redis。
補充下:ehcache也有快取共享方案,不過是通過RMI或者Jgroup多播方式進行廣播快取通知更新,快取共享複雜,維護不方便;簡單的共享可以,但是涉及到快取恢復,大資料快取,則不合適。
使用Redis有哪些好處?
(1) 速度快,因為資料存在記憶體中,類似於HashMap,HashMap的優勢就是查詢和操作的時間複雜度都是O(1)
(2) 支援豐富資料型別,支援string,list,set,sorted set,hash
(3) 支援事務,操作都是原子性,所謂的原子性就是對資料的更改要麼全部執行,要麼全部不執行
(4) 豐富的特性:可用於快取,訊息,按key設定過期時間,過期後將會自動刪除
JavaScript中定時器使用
setTimeout()
setTimeout函式用來指定某個函式或某段程式碼,在多少毫秒之後執行。它返回一個整數,表示定時器的編號,以後可以用來取消這個定時器。
setInterval()
setInterval函式的用法與setTimeout完全一致,區別僅僅在於setInterval指定某個任務每隔一段時間就執行一次,也就是無限次的定時執行。
// 執行在面的程式碼塊會輸出什麼?
setTimeout(function () {
console.log('timeout');
}, 1000);
setInterval(function () {
console.log('interval')
}, 1000);
// 輸出一次 timeout,每隔1S輸出一次 interval
關閉定時器的方法:clearInterval(),clearTimeout
setTimeout和setInterval函式,都返回一個表示計數器編號的整數值,將該整數傳入clearTimeout和clearInterval函式,就可以取消對應的定時器。
var id1 = setTimeout(f,1000);
var id2 = setInterval(f,1000);
clearTimeout(id1);
clearInterval(id2);
Spring框架IOC和AOP的實現原理
IOC: Inversion of Control(控制反轉)是指容器控制程式物件之間的關係,而不是傳統實現中,由程式程式碼直接操控。控制權由應用程式碼中轉到了外部容器,控制權的轉移是所謂反轉。
DI: Dependency Injection,即“依賴注入”。它並不是一種技術實現,而是一種設計思想。從名字上理解,所謂依賴注入,即元件之間的依賴關係由容器在執行期決定,即由容器動態地將某種依賴關係注入到元件之中。
依賴注入的思想是通過反射機制實現的,在例項化一個類時,它通過反射呼叫類中set方法將事先儲存在HashMap中的類屬性注入到類中。
優點
第一,資源集中管理,實現資源的可配置和易管理,降低物件關係維護的複雜度。
第二,降低了使用資源雙方的依賴程度,也就是我們說的耦合度。
舉例:某一天,你生病了,但是你不清楚自己到底得了什麼病,你只知道自己頭疼,咳嗽,全身無力。這個時候你決定去藥店買藥,藥店有很多種藥,僅僅是治療頭疼就有好幾十種,還有西藥中藥等區別。然後你自己看了看說明書,選擇了一盒你自己覺得最能治療自己病症的藥,付錢吃藥,期待可以早點好起來。
但是這個過程,對於一個病人來說,太辛苦了。頭疼,咳嗽,全身無力,還要一個個的看藥品說明書,一個個的比較哪個藥比較好,簡直是太累了。這個時候,你決定直接去醫院看醫生。
醫生給你做了檢查,知道你的病症是什麼,有什麼原因引起的;同時醫生非常瞭解有哪些藥能治療你的病痛,並且能根據你的自身情況進行篩選。只需要短短的十幾分鍾,你就能拿到對症下藥的藥品,即省時又省力。
在上面這個例子中,IOC起到的就是醫生的作用,它收集你的需求要求,並且對症下藥,直接把藥開給你。你就是物件,藥品就是你所需要的外部資源。通過醫生,你不用再去找藥品,而是通過醫生把藥品開給你。這就是整個IOC的精髓所在。
AOP(Aspect Oriented Programming)
AOP面向方面程式設計基於IoC,是對OOP的有益補充;
AOP利用一種稱為“橫切”的技術,剖解開封裝的物件內部,並將那些影響了 多個類的公共行為封裝到一個可重用模組,並將其名為“Aspect”,即方面。所謂“方面”,簡單地說,就是將那些與業務無關,卻為業務模組所共同呼叫的 邏輯或責任封裝起來,比如日誌記錄,便於減少系統的重複程式碼,降低模組間的耦合度,並有利於未來的可操作性和可維護性。
使用“橫切”技術,AOP把軟體系統分為兩個部分:核心關注點(業務邏輯)和橫切關注點(通用邏輯,即方面)。業務處理的主要流程是核心關注點,與之關係不大的部分是橫切關注點。橫切關注點的特點是,其經常發生在核心關注點的多處,而各處都基本相似。比如許可權認證、日誌、事務處理,debug管理,效能檢測等。AOP 的作用在於分離系統中的各種關注點,將核心關注點和橫切關注點分離開來。
2. 實現方式
實現AOP的技術,主要分為兩大類:
一是採用動態代理技術,利用擷取訊息的方式,對該訊息進行裝飾,以取代原有物件行為的執行;
二是採用靜態織入的方式,引入特定的語法建立“方面”,從而使得編譯器可以在編譯期間織入有關“方面”的程式碼。
3. 優點
①.橫切關注點的程式碼都集中於一塊,不再是分散在各個業務元件中,不會出現大量重複程式碼;
②.核心模組只關注核心功能的程式碼,與通用模組分離,模組間藕合度降低。
Java執行時記憶體分配
執行緒獨有區域:
程式計數器:
是JVM分配的較小的一塊記憶體空間,它可以看作是當前執行緒所執行的位元組碼的行號指示器。
位元組碼直譯器工作時就是通過改變這個計數器的值來選取下一條需要執行的位元組碼指令。
虛擬機器棧:
描述的是java方法執行的記憶體模型,每個方法在執行的同時都會建立一個棧幀用於儲存區域性變量表、運算元棧、動態連結方法出口等資訊。
棧幀也叫過程活動記錄,是編譯器用來實現過程/函式呼叫的一種資料結構。
執行緒啟動——執行緒中方法按使用順序入棧——方法入棧時建立棧幀
本地方法棧:
它與虛擬機器棧發揮的作用非常相似,區別只在於,虛擬機器棧為虛擬機器執行java方法,而本地方法棧則為用到的本地方法服務。
所有執行緒共享區域:
堆:
此記憶體區域的唯一目的就是存放物件例項,所有的物件例項以及陣列都要在堆上分配記憶體。
堆是垃圾收集器管理的主要區域。
方法區:
是各個執行緒共享的記憶體區域,它用來儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料。
Java 堆和棧的區別
概述
在Java中,記憶體分為兩種,一種是棧記憶體,另一種就是堆記憶體。
2、堆記憶體
1.什麼是堆記憶體?
堆記憶體是是Java記憶體中的一種,它的作用是用於儲存Java中的物件和陣列,當我們new一個物件或者建立一個數組的時候,就會在堆記憶體中開闢一段空間給它,用於存放。
2.堆記憶體的特點是什麼?
第一點:堆其實可以類似的看做是管道,或者說是平時去排隊買票的的情況差不多,所以堆記憶體的特點就是:先進先出,後進後出,也就是你先排隊,好,你先買票。
第二點:堆可以動態地分配記憶體大小,生存期也不必事先告訴編譯器,因為它是在執行時動態分配記憶體的,但缺點是,由於要在執行時動態分配記憶體,存取速度較慢。
3.new物件在堆中如何分配?
由Java虛擬機器的自動垃圾回收器來管理
3、棧記憶體
1.什麼是棧記憶體
棧記憶體是Java的另一種記憶體,主要是用來執行程式用的,比如:基本型別的變數和物件的引用變數
2.棧記憶體的特點
第一點:棧記憶體就好像一個礦泉水瓶,像裡面放入東西,那麼先放入的沉入底部,所以它的特點是:先進後出,後進先出
第二點:存取速度比堆要快,僅次於暫存器,棧資料可以共享,但缺點是,存在棧中的資料大小與生存期必須是確定的,缺乏靈活性
3.棧記憶體分配機制
棧記憶體可以稱為一級快取,由垃圾回收器自動回收
4、棧和堆的區別
JVM是基於堆疊的虛擬機器.JVM為每個新建立的執行緒都分配一個堆疊.也就是說,對於一個Java程式來說,它的執行就是通過對堆疊的操作來完成的。堆疊以幀為單位儲存執行緒的狀態。JVM對堆疊只進行兩種操作:以幀為單位的壓棧和出棧操作。
差異
1.堆記憶體用來存放由new建立的物件和陣列。
2.棧記憶體用來存放方法或者區域性變數等
3.堆是先進先出,後進後出
4.棧是後進先出,先進後出
相同
1.都是屬於Java記憶體的一種
2.系統都會自動去回收它,但是對於堆記憶體一般開發人員會自動回收它
資料庫事務四大特性(ACID)
Spring事務管理基於底層資料庫本身的事務處理機制。資料庫事務的基礎,是掌握Spring事務管理的基礎。
事務具備ACID四種特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔離性)和Durability(永續性)的英文縮寫。
原子性(Atomicity):事務作為一個整體被執行,包含在其中的對資料庫的操作要麼全部被執行,要麼都不執行。
一致性(Consistency):事務應確保資料庫的狀態從一個一致狀態轉變為另一個一致狀態。一致狀態的含義是資料庫中的資料應滿足完整性約束。
隔離性(Isolation):多個事務併發執行時,一個事務的執行不應影響其他事務的執行。
永續性(Durability):一個事務一旦提交,他對資料庫的修改應該永久儲存在資料庫中。
資料庫在不同的隔離性級別下併發訪問可能會出現以下幾種問題:
髒讀(Dirty Read)
當一個事務讀取另一個事務尚未提交的修改時,產生髒讀
不可重複讀(Unrepeatable Read)
一個事務範圍內多次查詢卻返回了不同的資料值,這是由於在查詢間隔,被另一個事務修改並提交了
幻讀(Phantom Read)
一個事務先後讀取一個範圍的記錄,但兩次讀取的資料不同,我們稱之為幻象讀(兩次執行同一條 select 語句會出現不同的結果,第二次讀會增加一資料行,並沒有說這兩次執行是在同一個事務中)
現在來看看MySQL資料庫為我們提供的四種隔離級別:
① Serializable (序列化)就是序列化:可避免髒讀、不可重複讀、幻讀的發生。
② Repeatable read (可重複讀):可避免髒讀、不可重複讀的發生。
③ Read committed (讀已提交):可避免髒讀的發生。
④ Read uncommitted (讀未提交):最低級別,任何情況都無法保證。
以上四種隔離級別最高的是Serializable級別,最低的是Read uncommitted級別,當然級別越高,執行效率就越低。像Serializable這樣的級別,就是以鎖表的方式(類似於Java多執行緒中的鎖)使得其他的執行緒只能在鎖外等待,所以平時選用何種隔離級別應該根據實際情況。在MySQL資料庫中預設的隔離級別為Repeatable read (可重複讀)。
在MySQL資料庫中,支援上面四種隔離級別,預設的為Repeatable read (可重複讀);而在Oracle資料庫中,只支援Serializable (序列化)級別和Read committed (讀已提交)這兩種級別,其中預設的為Read committed級別。
記住:設定資料庫的隔離級別一定要是在開啟事務之前!
如果是使用JDBC對資料庫的事務設定隔離級別的話,也應該是在呼叫Connection物件的setAutoCommit(false)方法之前。
css樣式優先順序問題
通用選擇器(*) < 元素(型別)選擇器 < class類選擇器 < 屬性選擇器 < 偽類 < ID 選擇器 < style內聯樣式
*{width:100px}通用選擇器(*)
.img{width:400px;}類class選擇器
img[alt="img"] {width:30