synchronized是Java中的關(guān)鍵字,是一種同步鎖。
無論synchronized關(guān)鍵字加在方法上還是對(duì)象上,如果它作用的對(duì)象是非靜態(tài)的,則它取得的鎖是對(duì)象;
如果synchronized作用的對(duì)象是一個(gè)靜態(tài)方法或一個(gè)類,則它取得的鎖是該類所有的對(duì)象。
JAVA的垃圾回收機(jī)制
1.1引用計(jì)數(shù)法:
通過引用計(jì)數(shù)來判斷一個(gè)對(duì)象是否可以被回收。如果一個(gè)對(duì)象沒有任何引用與之關(guān)聯(lián),則說明該對(duì)象基本不太可能在其他地方被使用到,那么這個(gè)對(duì)象就成為可被回收的對(duì)象了。
存在的問題:object1和object2賦值為null,也就是說object1和object2指向的對(duì)象已經(jīng)不可能再被訪問,但是由于它們互相引用對(duì)方,導(dǎo)致它們的引用計(jì)數(shù)器都不為0,那么垃圾收集器就永遠(yuǎn)不會(huì)回收它們。
1.2標(biāo)記-清除 算法:
從根集合進(jìn)行掃描,對(duì)存活的對(duì)象對(duì)象標(biāo)記,標(biāo)記完畢后,再掃描整個(gè)空間中未被標(biāo)記的對(duì)象,進(jìn)行回收。
存在的問題:由于直接回收不存活的對(duì)象,因此會(huì)造成內(nèi)存碎片。碎片太多可能會(huì)導(dǎo)致后續(xù)過程中需要為大對(duì)象分配空間時(shí)無法找到足夠的空間而提前觸發(fā)新的一次垃圾收集動(dòng)作。
1.3Copying(復(fù)制)算法:
將可用內(nèi)存按容量劃分為大小相等的兩塊,每次只使用其中的一塊。當(dāng)這一塊的內(nèi)存用完了,就將還存活著的對(duì)象復(fù)制到另外一塊上面,然后再把已使用的內(nèi)存空間一次清理掉,這樣一來就不容易出現(xiàn)內(nèi)存碎片的問題。
存在的問題:對(duì)內(nèi)存空間的使用做出了高昂的代價(jià),因?yàn)槟軌蚴褂玫膬?nèi)存縮減到原來的一半。
1.4generation算法:
分代收集算法是目前大部分JVM的垃圾收集器采用的算法。
一般情況下將堆區(qū)劃分為老年代和新生代。
老年代的特點(diǎn)是每次垃圾收集時(shí)只有少量對(duì)象需要被回收,而新生代的特點(diǎn)是每次垃圾回收時(shí)都有大量的對(duì)象需要被回收,那么就可以根據(jù)不同代的特點(diǎn)采取最適合的收集算法。
所有新生成的對(duì)象首先都是放在年輕代的。年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。
在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。
System.gc()用于調(diào)用垃圾收集器,在調(diào)用時(shí),垃圾收集器將運(yùn)行以回收未使用的內(nèi)存空間。它將嘗試釋放被丟棄對(duì)象占用的內(nèi)存。
2.1 GC
GC又分為minor GC 和 Full Gc。
Java 堆內(nèi)存分為新生代和老年代,新生代中又分為1個(gè)Eden區(qū)域 和兩個(gè) Survivor區(qū)域。
eden就相當(dāng)于是使用空間,survivor就相當(dāng)于是保留空間
Minor GC 的觸發(fā)條件:大多數(shù)情況下,直接在 Eden 區(qū)中進(jìn)行分配。如果 Eden區(qū)域沒有足夠的空間,那么就會(huì)發(fā)起一次 Minor GC。
對(duì)于 Full GC的觸發(fā)條件:也是如果老年代沒有足夠空間的話,那么就會(huì)進(jìn)行一次 Full GC。
*Hashtable
1.1什么時(shí)候用Hashtable
如果用到了Key,Value類型的數(shù)據(jù),就用Hashtable。
1.2usage
Hashtable<String, Integer> table = new Hashtable<String, Integer>();
table.put("zhangsan", 22);
table.remove("Beijing");
int value = table.get(key);
//Iterator遍歷方式1--鍵值對(duì)遍歷entrySet()
Iterator<Entry<String, Integer>> iter = table.entrySet().iterator();
while(iter.hasNext()){
Map.Entry<String, Integer> entry = (Map.Entry<String, Integer>)iter.next();
String key = entry.getKey();
int value = entry.getValue();
System.out.println("entrySet:"+key+" "+value);
}
//Iterator遍歷方式2--key鍵的遍歷
Iterator<String> iterator = table.keySet().iterator();
keySet() //返回值是個(gè)只存放key值的Set集合
返回映射所包含的映射關(guān)系的Set集合(一個(gè)關(guān)系就是一個(gè)鍵-值對(duì))
一些基礎(chǔ)問題:
1、訪問修飾符不寫(默認(rèn))?
類的成員不寫訪問修飾時(shí)默認(rèn)為default。
默認(rèn)對(duì)于同一個(gè)包中的其他類相當(dāng)于公開(public),對(duì)于不是同一個(gè)包中的其他類相當(dāng)于私有(private)。
2、String 是最基本的數(shù)據(jù)類型嗎?
不是。
Java中的基本數(shù)據(jù)類型只有8個(gè):byte、short、int、long、float、double、char、boolean;除了基本類型(primitive type)和枚舉類型(enumeration type),剩下的都是引用類型(reference type)。
3、內(nèi)存中的棧(stack)、堆(heap)和靜態(tài)區(qū)(static area)的用法?
我們定義一個(gè)基本數(shù)據(jù)類型的變量,一個(gè)對(duì)象的引用,還有就是函數(shù)調(diào)用的現(xiàn)場(chǎng)保存都使用內(nèi)存中的棧空間;
而通過new關(guān)鍵字和構(gòu)造器創(chuàng)建的對(duì)象放在堆空間;
程序中的字面量(literal)如直接書寫的100、”hello”和常量都是放在靜態(tài)區(qū)中。
String str = new String("hello");
上面的語句中變量str放在棧上,用new創(chuàng)建出來的字符串對(duì)象放在堆上,而”hello”這個(gè)字面量放在靜態(tài)區(qū)。
4、數(shù)組有沒有l(wèi)ength()方法?String有沒有l(wèi)ength()方法?
答:數(shù)組沒有l(wèi)ength()方法,有l(wèi)ength 的屬性。String 有l(wèi)ength()方法。
5、在Java中,如何跳出當(dāng)前的多重嵌套循環(huán)?
在最外層循環(huán)前加一個(gè)標(biāo)記如A,然后用break A;可以跳出多重循環(huán)。
6、兩個(gè)對(duì)象值相同(x.equals(y) == true),hashcode應(yīng)該相同
(1)如果兩個(gè)對(duì)象相同(equals方法返回true),那么它們的hashCode值一定要相同;
(2)如果兩個(gè)對(duì)象的hashCode相同,它們并不一定相同。
如果你違背了上述原則就會(huì)發(fā)現(xiàn)在使用容器時(shí),相同的對(duì)象可以出現(xiàn)在Set集合中,同時(shí)增加新元素的效率會(huì)大大下降
7、arraylist與vector的區(qū)別
a、Vector的方法都是同步的(Synchronized),是線程安全的(thread-safe),而ArrayList的方法不是,由于線程的同步必然要影響性能,因此,ArrayList的性能比Vector好。
b、 當(dāng)Vector或ArrayList中的元素超過它的初始大小時(shí),Vector會(huì)將它的容量翻倍,而ArrayList只增加50%的大小, ArrayList就有利于節(jié)約內(nèi)存空間。
線程安全就是多線程訪問時(shí),采用了加鎖機(jī)制,當(dāng)一個(gè)線程訪問該類的某個(gè)數(shù)據(jù)時(shí),進(jìn)行保護(hù),其他線程不能進(jìn)行訪問直到該線程讀取完,其他線程才可使用
8、Hashtable和HashMap的區(qū)別
HashMap是非線程安全的,非synchronized,只是用于單線程環(huán)境下,可以接受null
(key為null的鍵值對(duì)永遠(yuǎn)都放在以table[0]為頭結(jié)點(diǎn)的鏈表中)
Hashtable是線程安全的,多個(gè)線程可以共享一個(gè)Hashtable,也是synchronized,所以在單線程環(huán)境下它比HashMap要慢。
JAVA中的同步與異步:
同步:指發(fā)送一個(gè)請(qǐng)求,需要等待返回,然后才能夠發(fā)送下一個(gè)請(qǐng)求,有個(gè)等待過程;
異步:指發(fā)送一個(gè)請(qǐng)求,不需要等待返回,隨時(shí)可以再發(fā)送下一個(gè)請(qǐng)求,即不需要等待。
并行其實(shí)是真正的異步,并發(fā)偽異步。
9、是否可以繼承String類?
String 類是final類,不可以被繼承。
10、String和StringBuilder、StringBuffer的區(qū)別?
String是只讀字符串,也就意味著String引用的字符串內(nèi)容是不能被改變的。
而StringBuffer/StringBuilder類表示的字符串對(duì)象可以直接進(jìn)行修改。StringBuilder是在單線程環(huán)境下使用的,因此它的效率也比StringBuffer要高。
11、char 型變量中能不能存貯一個(gè)中文漢字,為什么?
char類型可以存儲(chǔ)一個(gè)中文漢字,因?yàn)镴ava中使用的編碼是Unicode,一個(gè)char類型占2個(gè)字節(jié)
12、抽象類和接口有什么異同?
a、抽象類和接口都不能夠?qū)嵗?/strong>
b、一個(gè)類如果繼承了某個(gè)抽象類或者實(shí)現(xiàn)了某個(gè)接口都需要對(duì)其中的抽象方法全部進(jìn)行實(shí)現(xiàn),否則該類仍然需要被聲明為抽象類。
**如果一個(gè)類里有抽象方法,那么這個(gè)類只能是抽象類 **
不同:
c、而接口中不能定義構(gòu)造器而且其中的方法全部都是抽象方法。,抽象類里可以沒有抽象方法 **
d、抽象類中的成員可以是private、默認(rèn)、protected、public的,而接口中的成員全都是public的。**
e、抽象類中可以定義成員變量,而接口中定義的成員變量實(shí)際上都是public static 常量。
f、接口可繼承接口,并可多繼承接口,但類只能單繼承。
g、接口只能做方法申明,抽象類中可以做方法申明,也可以做方法實(shí)現(xiàn)
實(shí)現(xiàn)接口或繼承抽象類的子類必須實(shí)現(xiàn)接口的所有方法或抽象類的所有抽象方法。
接口中的成員不能有任何實(shí)現(xiàn)
13、抽象的(abstract)方法是否可同時(shí)是靜態(tài)的(static)?
不能。抽象方法需要子類重寫,而靜態(tài)的方法是無法被重寫的,因此二者是矛盾的。
14、是否可以從一個(gè)靜態(tài)(static)方法內(nèi)部發(fā)出對(duì)非靜態(tài)(non-static)方法的調(diào)用?
不可以,靜態(tài)方法只能訪問靜態(tài)成員,因?yàn)榉庆o態(tài)方法的調(diào)用要先創(chuàng)建對(duì)象,在調(diào)用靜態(tài)方法時(shí)可能對(duì)象并沒有被初始化。
15、GC是什么?為什么要有GC?
GC是垃圾收集的意思,內(nèi)存處理是編程人員容易出現(xiàn)問題的地方,忘記或者錯(cuò)誤的內(nèi)存回收會(huì)導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰,Java提供的GC功能可以自動(dòng)監(jiān)測(cè)對(duì)象是否超過作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的,Java語言沒有提供釋放已分配內(nèi)存的顯示操作方法。Java程序員不用擔(dān)心內(nèi)存管理,因?yàn)槔占鲿?huì)自動(dòng)進(jìn)行管理。
要請(qǐng)求垃圾收集,可以調(diào)用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉顯示的垃圾回收調(diào)用。
16、內(nèi)部類可以引用它的包含類(外部類)的成員嗎?有沒有什么限制?
一個(gè)內(nèi)部類對(duì)象可以訪問創(chuàng)建它的外部類對(duì)象的成員,包括私有成員。
17、Java 中的final關(guān)鍵字有哪些用法?
(1)修飾類:表示該類不能被繼承;(2)修飾方法:表示方法不能被重寫;(3)修飾變量:表示變量只能一次賦值以后值不能被修改(常量)。
18、 如何將字符串轉(zhuǎn)換為基本數(shù)據(jù)類型?如何將基本數(shù)據(jù)類型轉(zhuǎn)換為字符串?
調(diào)用基本數(shù)據(jù)類型對(duì)應(yīng)的包裝類中的方法parseXXX(String)或valueOf(String)即可返回相應(yīng)基本類型;
19、Thread類的sleep()方法和對(duì)象的wait()方法都可以讓線程暫停執(zhí)行,它們有什么區(qū)別?
sleep()方法(休眠)是線程類(Thread)的靜態(tài)方法,調(diào)用此方法會(huì)讓當(dāng)前線程暫停執(zhí)行指定的時(shí)間,將執(zhí)行機(jī)會(huì)(CPU)讓給其他線程,但是對(duì)象的鎖依然保持。
wait()是Object類的方法,調(diào)用對(duì)象的wait()方法導(dǎo)致當(dāng)前線程放棄對(duì)象的鎖(線程暫停執(zhí)行),進(jìn)入對(duì)象的等待池(wait pool),只有調(diào)用對(duì)象的notify()方法才能喚醒等待池中的線程進(jìn)入等鎖池(lock pool)。
20、Static
在static方法內(nèi)部不能調(diào)用非靜態(tài)方法,反過來是可以的。而且可以在沒有創(chuàng)建任何對(duì)象的前提下,僅僅通過類本身來調(diào)用static方法。這實(shí)際上正是static方法的主要用途。
21、JAVA字符串的操作
截取字符串:
String sb = "bbbdsajjds";
sb.substring(2, 4);
從索引號(hào)2開始到索引4結(jié)束(并且不包含索引4截取在內(nèi));
StringBuffer的方法:
StringBuffer sb2 = new StringBuffer(s); //String轉(zhuǎn)換為StringBuffer
String s1 = sb2.toString(); //StringBuffer轉(zhuǎn)換為String
sb2.append("aaa")該方法的作用是追加內(nèi)容到當(dāng)前StringBuffer對(duì)象的末尾
insert(int offset, boolean b)
sb.reverse();
22、日期
如何格式化日期
DateFormate df=DateFormate.getInstance();
df.Format(dat);
如何取得年月日,小時(shí)分秒
Date dat=new Date();
dat.getYear(); dat.getMonth(); dat.getDay(); dat.getHours();dat.getSeconds();
23、I/O操作
InputStream/OutputStream 都是父類,都是抽象類。
FileOutputStream/FileInputStream 本地文件
read &&write 方法
24、JAVA多線程
指的是這個(gè)程序(一個(gè)進(jìn)程)運(yùn)行時(shí)產(chǎn)生了不止一個(gè)線程

啟動(dòng)一個(gè)線程的方法:
MyThread my = new MyThread();
my.start();
25、什么樣的字段適合做索引
表的主鍵、外鍵必須有索引;
經(jīng)常與其他表進(jìn)行連接的表,在連接字段上應(yīng)該建立索引;
經(jīng)常出現(xiàn)在Where子句中的字段,特別是大表的字段,應(yīng)該建立索引;
26、JAVA的多態(tài)
重寫
接口
抽象類和抽象方法
27、同步、異步、阻塞、非阻塞概念
同步、異步:關(guān)注的是如何獲取結(jié)果,直接獲取還是等待通知。
阻塞和非阻塞是指進(jìn)程訪問的數(shù)據(jù)如果尚未就緒,進(jìn)程是否需要等待
阻塞,就是調(diào)用結(jié)果返回之前,該執(zhí)行線程會(huì)被掛起,不釋放CPU執(zhí)行權(quán),線程不能做其它事情,只能等待,只有等到調(diào)用結(jié)果返回了,才能繼續(xù);
非阻塞,就是在沒有獲取調(diào)用結(jié)果時(shí),不是一直等待,線程可以往下執(zhí)行
28、線程掛起
線程掛起和恢復(fù)方法1:wait()與notify()方法
線程掛起2:sleep()方法
29、java GC是在什么時(shí)候,對(duì)什么東西,做了什么事情?
對(duì)什么東西:從GC Roots搜索不到,而且經(jīng)過一次標(biāo)記清理之后仍沒有復(fù)活的對(duì)象。
做什么:
新生代:復(fù)制清理;
老年代:標(biāo)記-清除和標(biāo)記-壓縮算法;
永久代:存放Java中的類和加載類的類加載器本身。
30、講講類的實(shí)例化順序,當(dāng) new 的時(shí)候, 他們的執(zhí)行順序。
父類靜態(tài)代變量、
父類靜態(tài)代碼塊、
子類靜態(tài)變量、
子類靜態(tài)代碼塊、
父類非靜態(tài)變量(父類實(shí)例成員變量)、
父類構(gòu)造函數(shù)、
子類非靜態(tài)變量(子類實(shí)例成員變量)、
子類構(gòu)造函數(shù)。
31、LinkedList
LinkedList的本質(zhì)是雙向鏈表。
LinkedList包含兩個(gè)重要的成員:header 和 size。
//迭代器遍歷
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()){
iterator.next();
}
分配內(nèi)存空間不是必須是連續(xù)的;
插入、刪除操作很快,只要修改前后指針就OK了,時(shí)間復(fù)雜度為O(1);
void add(int index, E element):在指定位置插入一個(gè)元素。
32、核心 Map
HashMap
Hashtable
entrySet()返回 Map 中所包含映射的 Set 視圖。
Set 中的每個(gè)元素都是一個(gè) Map.Entry 對(duì)象,可以使用 getKey() 和 getValue() 方法(還有一個(gè) setValue() 方法)訪問后者的鍵元素和值元素
equals(Object o) 比較指定對(duì)象與此 Map 的等價(jià)性
hashCode() 返回此 Map 的哈希碼
33、I/O模型
所有的系統(tǒng)I/O都分為兩個(gè)階段:等待就緒和操作。讀函數(shù),分為等待系統(tǒng)可讀和真正的讀;同寫函數(shù)分為等待網(wǎng)卡可以寫和真正的寫。
同步阻塞的BIO、同步非阻塞的NIO、異步非阻塞的AIO。
34、JAVA反射機(jī)制提供了什么功能
獲取類的Class對(duì)象
獲取類的Fields
獲取類的Method
獲取類的Constructor
新建類的實(shí)例
35、動(dòng)態(tài)代理
若代理類在程序運(yùn)行前就已經(jīng)存在,那么這種代理方式被成為【靜態(tài)代理】 ,這種情況下的代理類通常都是我們?cè)贘ava代碼中定義的。
代理類:
public interface FontProvider {
Font getFont(String name);
}
public abstract class ProviderFactory {
public static FontProvider getFontProvider() {
return new FontProviderFromDisk();
}
}
現(xiàn)在我們希望給他加上一個(gè)緩存功能,我們可以用靜態(tài)代理來完成
public class CachedFontProvider implements FontProvider {
private FontProvider fontProvider;
private Map<String, Font> cached;
public CachedFontProvider(FontProvider fontProvider) {
this.fontProvider = fontProvider;
}
……
}
/* 對(duì)工廠類進(jìn)行相應(yīng)修改,代碼使用處不必進(jìn)行任何修改。
這也是面向接口編程以及工廠模式的一個(gè)好處 */
public abstract class ProviderFactory {
public static FontProvider getFontProvider() {
return new CachedFontProvider(new FontProviderFromDisk());
}
}
}
動(dòng)態(tài)代理:考慮以下各種情況,有多個(gè)提供類,每個(gè)類都有g(shù)etXxx(String name)方法,每個(gè)類都要加入緩存功能,使用靜態(tài)代理雖然也能實(shí)現(xiàn),但是也是略顯繁瑣,需要手動(dòng)一一創(chuàng)建代理類。
public class CachedProviderHandler implements InvocationHandler {
private Map<String, Object> cached = new HashMap<>();
private Object target;
public CachedProviderHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
……
}
return method.invoke(target, args);
}
}
public abstract class ProviderFactory {
public static FontProvider getFontProvider() {
Class<FontProvider> targetClass = FontProvider.class;
return (FontProvider) Proxy.newProxyInstance(targetClass.getClassLoader(),
new Class[] { targetClass },
new CachedProviderHandler(new FontProviderFromDisk()));
}
}
主要用來做方法的增強(qiáng),讓你可以在不修改源碼的情況下,增強(qiáng)一些方法,在方法執(zhí)行前后做任何你想做的事情(甚至根本不去執(zhí)行這個(gè)方法),因?yàn)樵贗nvocationHandler的invoke方法中,你可以直接獲取正在調(diào)用方法對(duì)應(yīng)的Method對(duì)象,具體應(yīng)用的話,比如可以添加調(diào)用日志,做事務(wù)控制等。
36、jvm 中一次完整的 GC 流程是怎樣的
對(duì)象誕生即新生代->eden,在進(jìn)行minor gc過程中,如果依舊存活,移動(dòng)到from,變成Survivor,進(jìn)行標(biāo)記代數(shù),如此檢查一定次數(shù)后,晉升為老年代
37、線程的掛起和喚醒
notify( )方法,喚醒在此對(duì)象監(jiān)視器上等待的單個(gè)線程,只會(huì)通知等待隊(duì)列中的第一個(gè)相關(guān)線程。
wait( )放棄當(dāng)前對(duì)資源的占有權(quán), 導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的notify( ) 方法或 notifyAll( ) 方法
sleep()方法使線程進(jìn)入休眠狀態(tài),線程在指定時(shí)間內(nèi)不會(huì)運(yùn)行。
join()方法使線程掛起,使自己等待另一個(gè)線程的結(jié)果,直到另一個(gè)線程執(zhí)行完畢為止。
38、導(dǎo)致線程死鎖的原因?怎么解除線程死鎖?
- 互斥條件:一個(gè)資源每次只能被一個(gè)線程使用。
- 請(qǐng)求與保持條件:一個(gè)進(jìn)程因請(qǐng)求資源而阻塞時(shí),對(duì)已獲得的資源保持不放。
- 不剝奪條件:進(jìn)程已獲得的資源,在未使用完之前,不能強(qiáng)行剝奪。
- 循環(huán)等待條件:若干進(jìn)程之間形成一種頭尾相接的循環(huán)等待資源關(guān)系。
只要破壞死鎖 4 個(gè)必要條件之一中的任何一個(gè),死鎖問題就能被解決。
39、簡(jiǎn)述 Http 請(qǐng)求 get 和 post 的區(qū)別以及數(shù)據(jù)包格式。

get大小有限制,post沒有限制
40、聚集索引和非聚集索引的區(qū)別。
聚集索引就是索引和記錄緊密在一起。
非聚簇索引 索引文件和數(shù)據(jù)文件分開存放,索引文件的葉子頁只保存了主鍵值,要定位記錄還要去查找相應(yīng)的數(shù)據(jù)塊。
41、ACID 是什么。
atomic,原子性,要么都提交,要么都失敗,不能一部分成功,一部分失敗。
consistent,一致性,事物開始及結(jié)束后,數(shù)據(jù)的一致性約束沒有被破壞
isolation,隔離性,并發(fā)事物間相互不影響,互不干擾。
durability,持久性,已經(jīng)提交的事物對(duì)數(shù)據(jù)庫(kù)所做的更新必須永久保存。即便發(fā)生崩潰,也不能被回滾或數(shù)據(jù)丟失。
42、