亚洲精品中文字幕无乱码_久久亚洲精品无码AV大片_最新国产免费Av网址_国产精品3级片

范文資料網(wǎng)>人事資料>招聘與面試>《java面試中常問的問題

java面試中常問的問題

時間:2022-04-05 14:28:17 招聘與面試 我要投稿
  • 相關(guān)推薦

java面試中常問的問題

1、請說出作用域public,private,protected,以及不寫時的區(qū)別

java面試中常問的問題

這四個作用域的可見范圍如下表所示。

說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示 friendly 。

作用域 當前類 同一 package 子孫類 其他 package

public    √ √ √ √

protected  √ √ √ ×

friendly   √ √ × ×

private     √ × × ×

備注:只要記住了有 4 種訪問權(quán)限, 4 個訪問范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫出上面的圖了。

2、Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?

重載 Overload 表示同一個類中可以有多個名稱相同的方法 ,但這些方法的參數(shù)列表各不相同 (即參數(shù)個數(shù)或類型不同)。

重寫 Override 表示子類中的方法可以與父類中的某個方法的名稱和參數(shù)完全相同 ,通過子類創(chuàng)建的實例對象調(diào)用這個方法時,將調(diào)用子類中的定義方法 ,這相當于把父類中定義的那個完全相同的方法給覆蓋 了,這也是面向?qū)ο缶幊痰亩鄳B(tài)性 的一種表現(xiàn)。

如果兩個方法的參數(shù)列表完全一樣,是否可以讓它們的返回值不同來實現(xiàn)重載 Overload 。 java 就無法確定編程者倒底是想調(diào)用哪個方法了,因為它無法通過返回結(jié)果類型來判斷 。

http://emrowgh.com和Hashtable的區(qū)別

(1 )HashMap不是線程安全的 .

hashmap是一個接口 是map接口的子接口,是將鍵映射到值的對象,其中鍵和值都是對象 ,并且不能包含重復(fù)鍵 ,但可以包含重復(fù)值 。HashMap允許 null key 和 null value ,而hashtable不允許。

(2)   HashTable是線程安全的一個Collection。

HashMap是Hashtable的輕量級實現(xiàn)(非線程安全的實現(xiàn)),他們都完成了Map接口,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全,效率上可能高 于Hashtable。

HashMap允許將null作為一個entry的key或者value,而Hashtable 不允許 。

HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。

Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interf-ace的一個實現(xiàn)。

最大的不同是,Hashtable 的方法是 Synchronize 的,而HashMap不是,在多個線程訪問 Hashtable 時,不需要自己為它的方法實現(xiàn)同步 ,而HashMap 就必須為之提供外同步 。

Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會有很大的差異。

4. ArrayList 和 LinkedList

List 接口對 Collection 進行了簡單的擴充,它的具體實現(xiàn)類常用的有 ArrayList 和 LinkedList 。你可以將任何東西放到一個 List 容器中,并在需要時從中取出。 ArrayList 從其命名中可以看出它是一種類似數(shù)組 的形式進行存儲,因此它的隨機訪問速度極快 ,而 LinkedList 的內(nèi)部實現(xiàn)是鏈表, 它適合于在鏈表中間需要頻繁進行插入和刪除 操作。在具體應(yīng)用時可以根據(jù)需要自由選擇。前面說的 Iterator 只能對容器進行向前遍歷 ,而 ListIterator 則繼承了 Iterator 的思想,并提供了對 List 進行雙向遍歷 的方法。

5. .hashCode方法的作用?   

(網(wǎng)友提供的一段,待改進: hashcode這個方法是用來鑒定 2 個對象是否相等的 。

那你會說,不是還有equals這個方法嗎?

不錯,這2個方法都是用來判斷2個對象是否相等的。但是他們是有區(qū)別的。

一般來講,equals這個方法是給用戶調(diào)用的,如果你想判斷2個對象是否相等,你可以重寫equals方法,然后在代碼中調(diào)用,就可以判斷他們是否相等了。簡單來講,equals方法主要是用來判斷從表面上看或者從內(nèi)容上看,2個對象是不是相等。舉個例子,有個學生類,屬性只有姓名和性別,那么我們可以認為只要姓名和性別相等,那么就說這2個對象是相等的。

hashcode方法一般用戶不會去調(diào)用,比如在hashmap中,由于key是不可以重復(fù)的,他在判斷key是不是重復(fù)的時候就判斷了hashcode這個方法,而且也用到了equals方法。這里不可以重復(fù)是說equals和hashcode只要有一個不等就可以了!所以簡單來講,hashcode相當于是一個對象的編碼,就好像文件中的md5,他和equals不同就在于他返回的是 int 型 的,比較起來不直觀。我們一般在覆蓋equals的同時也要覆蓋hashcode,讓他們的邏輯一致。舉個例子,還是剛剛的例子,如果姓名和性別相等就算2個對象相等的話,那么hashcode的方法也要返回姓名的hashcode值加上性別的hashcode值,這樣從邏輯上,他們就一致了。

要從物理上判斷 2 個對象是否相等,用 == 就可以了。

6、靜態(tài)變量和實例變量的區(qū)別?

在語法定義上的區(qū)別:靜態(tài)變量前要加 static 關(guān)鍵字,而實例變量前則不加。

在程序運行時的區(qū)別:實例變量屬于某個對象的屬性,必須創(chuàng)建了實例對象 ,其中的實例變量才會被分配空間 ,才能使用這個實例變量。靜態(tài)變量不屬于某個實例對象,而是屬于類,所以也稱為類變量,只要程序加載了類的字節(jié)碼,不用創(chuàng)建任何實例對象,靜態(tài)變量就會被分配空間 ,靜態(tài)變量就可以被使用了?傊,實例變量必須創(chuàng)建對象后才可以通過這個對象來使用,靜態(tài)變量則可以直接使用類名來引用

7、Integer與int的區(qū)別

int 是 java 提供的 8 種原始數(shù)據(jù)類型之一 。 Java 為每個原始類型提供了封裝類, Integer 是 java為 int 提供的封裝類。 int 的默認值為 0 ,而 Integer 的默認值為 null ,即 Integer 可以區(qū)分出未賦值和值為 0 的區(qū)別 , int 則無法表達出未賦值的情況,

8、http://emrowgh.com(11.5)等於多少? http://emrowgh.com(-11.5)等於多少?

Math 類中提供了三個與取整有關(guān)的方法: ceil 、 floor 、 round ,這些方法的作用與它們的英文名稱的含義相對應(yīng),例如, ceil 的英文意義是天花板,該方法就表示向上取整 ,所以, http://emrowgh.com(11.3) 的結(jié)果為 12,http://emrowgh.com(-11.3) 的結(jié)果是 -11 ; floor 的英文意義是地板,該方法就表示向下取整 ,所以, http://emrowgh.com(11.6) 的結(jié)果為 11,http://emrowgh.com(-11.6) 的結(jié)果是 -12 ;最難掌握的是 round 方法,它表示“四舍五入”, 算法為 http://emrowgh.com(x+0.5) ,即將原來的數(shù)字加上 0.5 后再向下取整,所以,http://emrowgh.com(11.5)的結(jié)果為12,http://emrowgh.com(-11.5)的結(jié)果為-11。

http://emrowgh.com

(1).概念介紹:所謂AOP,即Aspect orientied program,就是面向方面 ( 切面 ) 的編程,

(2).解釋什么是方面:貫穿到系統(tǒng)的各個模塊中的系統(tǒng)一個功能就是一個方面,

比如,記錄日志,統(tǒng)一異常處理,事務(wù)處理,權(quán)限檢查 ,這些功能都是軟件系統(tǒng)

的一個面,而不是一點,在各個模塊中都要出現(xiàn)。

(3).什么是面向方面編程:把系統(tǒng)的一個方面的功能封裝成對象 的形式來處理

(4).怎么進行面向方面編程:把功能模塊對應(yīng)的對象作為切面嵌入到原來的各個系統(tǒng)模塊中,采用代理技術(shù),代理會調(diào)用目標 ,同時把切面功能的代碼(對象)加入 進來,所以,

用spring配置代理對象時只要要配兩個屬性,分別表示目標 和切面對象 (Advisor)。

10、構(gòu)造器Constructor是否可被override?

構(gòu)造器 Constructor 不能被繼承,因此不能重寫 Override ,但可以被重載 Overload 。

11、寫clone()方法時,通常都有一行代碼,是什么?

clone 有缺省行為 , http://emrowgh.com(); 因為首先要把父類中的成員復(fù)制到位,然后才是復(fù)制自己的成員。

12、java中實現(xiàn)多態(tài)的機制是什么?

靠的是父類或接口 定義的引用變量可以指向子類或具體實現(xiàn)類的實例對象,而程序調(diào)用的方法在運行期才動態(tài)綁定,就是引用變量所指向的具體實例對象的方法,也就是內(nèi)存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。

13、abstract class和interf-ace有什么區(qū)別?

含有 abstract 修飾符的 class 即為抽象類, abstract 類不能創(chuàng)建的實例對象 。含有 abstract 方法的類必須定義為 abstract class , abstract class 類中的方法不必是抽象的。 abstract class 類中定義抽象方法必須在具體 (Concrete) 子類中實現(xiàn),所以,不能有抽象構(gòu)造方法或抽象靜態(tài)方法 。如果的子類沒有實現(xiàn)抽象父類中的所有抽象方法,那么子類也必須定義為 abstract 類型。

接口( interf-ace )可以說成是抽象類的一種特例 ,接口中的所有方法都必須是抽象 的。接口中的方法定義默認為 public abstract 類型,接口中的成員變量類型默認為 public static final 。

下面比較一下兩者的語法區(qū)別:

1. 抽象類可以有構(gòu)造方法 ,接口中不能有 構(gòu)造方法。

2. 抽象類中可以有普通成員變量,接口中沒有普通成員變量

3. 抽象類中可以包含非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。

4. 抽象類中的抽象方法的訪問類型可以是 public , protected 和(默認類型 , 雖然

eclipse 下不報錯,但應(yīng)該也不行),但接口中的抽象方法只能是 public 類型的,并且默認即為 public abstract 類型。

5. 抽象類中可以包含靜態(tài) 方法,接口中不能包含 靜態(tài)方法

6. 抽象類和接口中都可以包含靜態(tài)成員 變量,抽象類中的靜態(tài)成員變量的訪問類型可以任意,但接口中定義的變量只能是 public static final 類型,并且默認即為 public static final 類型。

7. 一個類可以實現(xiàn)多個接口,但只能繼承一個抽象類。

下面接著再說說兩者在應(yīng)用上的區(qū)別:

接口更多的是在系統(tǒng)架構(gòu)設(shè)計方法發(fā)揮作用,主要用于定義模塊之間的通信契約。而抽象類在代碼實現(xiàn)方面發(fā)揮作用,可以實現(xiàn)代碼的重用,例如,模板方法設(shè)計模式是抽象類的一個典型應(yīng)用,假設(shè)某個項目的所有Servlet 類都要用相同的方式進行權(quán)限判斷、記錄訪問日志和處理異常,那么就可以定義一個抽象的基類,讓所有的 Servlet 都繼承這個抽象基類,在抽象基類的 service 方法中完成權(quán)限判斷、記錄訪問日志和處理異常的代碼,在各個子類中只是完成各自的業(yè)務(wù)邏輯代碼,偽代碼如下:

public abstract class BaseServlet extends HttpServlet

{

public final void service(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException

{

記錄訪問日志

進行權(quán)限判斷

if( 具有權(quán)限 )

{

try

{

doService(request,response);

}

catch(Excetpion e)

{

記錄異常信息

}

}

}

protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException; 

// 注意訪問權(quán)限定義成 protected ,顯得既專業(yè),又嚴謹,因為它是專門給子類用的

}

public class MyServlet1 extends BaseServlet

{

protected void doService(HttpServletRequest request, HttpServletResponse response) throws IOExcetion,ServletException

{

本 Servlet 只處理的具體業(yè)務(wù)邏輯代碼

}

}

父類方法中間的某段代碼不確定,留給子類干,就用模板方法設(shè)計模式。

備注:這道題的思路是先從總體解釋抽象類和接口的基本概念,然后再比較兩者的語法細節(jié),最后再說兩者的應(yīng)用區(qū)別。比較兩者語法細節(jié)區(qū)別的條理是:先從一個類中的構(gòu)造方法、普通成員變量和方法(包括抽象方法),靜態(tài)變量和方法,繼承性等 6 個方面逐一去比較回答,接著從第三者繼承的角度的回答,特別是最后用了一個典型的例子來展現(xiàn)自己深厚的技術(shù)功底。

14. jdk中哪些類是不能繼承的?

不能繼承的是類是那些用 final 關(guān)鍵字修飾的類。一般比較基本的類型或防止擴展類無意間破壞原來方法的實現(xiàn)的類型都應(yīng)該是 final 的,在 jdk 中 System ,String ,StringBuffer 等都是基本類型

15、String s = "Hello";s = s + " world!";這兩行代碼執(zhí)行后,原始的String對象中的內(nèi)容到底變了沒有?

沒有。因為String 被設(shè)計成不可變 (immutable) 類,所以它的所有對象都是不可變對象 。在這段代碼中,s原先指向一個String對象,內(nèi)容是 "Hello",然后我們對s進行了+操作,那么s所指向的那個對象是否發(fā)生了改變呢?答案是沒有。這時,s不指向原來那個對象了,而指向了另一個 String對象,內(nèi)容為"Hello world!",原來那個對象還存在于內(nèi)存之中,只是s這個引用變量不再指向它了。 

通過上面的說明,我們很容易導出另一個結(jié)論,如果經(jīng)常對字符串進行各種各樣的修改,或者說,不可預(yù)見的修改,那么使用String來代表字符串的話會引起很大的內(nèi)存開銷。因為 String對象建立之后不能再改變,所以對于每一個不同的字符串,都需要一個String對象來表示。這時,應(yīng)該考慮使用StringBuffer 類,它允許修改 ,而不是每個不同的字符串都要生成一個新的對象。并且,這兩種類的對象轉(zhuǎn)換十分容易。 

同時,我們還可以知道,如果要使用內(nèi)容相同的字符串,不必每次都new一個String。例如我們要在構(gòu)造器中對一個名叫s的String引用變量進行初始化,把它設(shè)置為初始值,應(yīng)當這樣做: 

public class Demo {

private String s;

...

public Demo {

s = "Initial Value";

}

...

}

而非 

s = new String("Initial Value");

后者每次都會調(diào)用構(gòu)造器,生成新對象,性能低下且內(nèi)存開銷大,并且沒有意義,因為String對象不可改變,所以對于內(nèi)容相同的字符串,只要一個String對象來表示就可以了。也就說,多次調(diào)用上面的構(gòu)造器創(chuàng)建多個對象,他們的String類型屬性s都指向同一個對象。 

上面的結(jié)論還基于這樣一個事實:對于字符串常量,如果內(nèi)容相同,Java認為它們代表同一個String對象。而用關(guān)鍵字new調(diào)用構(gòu)造器,總是會創(chuàng)建一個新的對象,無論內(nèi)容是否相同。 

至于為什么要把String類設(shè)計成不可變類,是它的用途決定的。其實不只String,很多Java標準類庫中的類都是不可變的。在開發(fā)一個系統(tǒng)的時候,我們有時候也需要設(shè)計不可變類,來傳遞一組相關(guān)的值,這也是面向?qū)ο笏枷氲捏w現(xiàn)。不可變類有一些優(yōu)點,比如因為它的對象是只讀的,所以多線程并發(fā)訪問也不會有任何問題。當然也有一些缺點,比如每個不同的狀態(tài)都要一個對象來代表,可能會造成性能上的問題。所以Java標準類庫還提供了一個可變版本,即 StringBuffer。

16、java中會存在內(nèi)存泄漏嗎,請簡單描述。

所謂內(nèi)存泄露就是指一個不再被程序使用的對象或變量一直被占據(jù)在內(nèi)存中。java中有垃圾回收機制,它可以保證一對象不再被引用的時候,即對象編程了孤兒的時候,對象將自動被垃圾回收器從內(nèi)存中清除掉。由于Java 使用有向圖的方式進行垃圾回收管理,可以消除引用循環(huán)的問題,例如有兩個對象,相互引用,只要它們和根進程不可達的,那么GC也是可以回收它們的,例如下面的代碼可以看到這種情況的內(nèi)存回收:

package http://emrowgh.com

import http://emrowgh.com

public class GarbageTest {

/**

@param args

@throws IOException

*/

public static void main(String[] args) throws IOException {

// TODO Auto-generated method stub

try {

gcTest ();

catch (IOException e) {

// TODO Auto-generated catch block

http://emrowgh.com();

}

http://emrowgh.com( "has exited gcTest!" );

http://emrowgh.com();

http://emrowgh.com();   

http://emrowgh.com( "out begin gc!" );     

for int i=0;i<100;i++)

{

http://emrowgh.com();

http://emrowgh.com();

http://emrowgh.com();

}

}

private static void gcTest() throws IOException {

http://emrowgh.com();

http://emrowgh.com();   

Person p1 = new Person();

http://emrowgh.com();

http://emrowgh.com();   

Person p2 = new Person();

http://emrowgh.com(p2);

http://emrowgh.com(p1);

http://emrowgh.com( "before exit gctest!" );

http://emrowgh.com();

http://emrowgh.com();   

http://emrowgh.com();

http://emrowgh.com( "exit gctest!" );

}

private static class Person

{

byte [] data = new byte [20000000];

Person mate = null ;

public void setMate(Person other)

{

mate = other;

}

}

}

java中的內(nèi)存泄露的情況: 長生命周期的對象持有短生命周期對象的引用 就很可能發(fā)生內(nèi)存泄露,盡管短生命周期對象已經(jīng)不再需要,但是因為長生命周期對象持有它的引用而導致不能被回收,這就是java中內(nèi)存泄露的發(fā)生場景,通俗地說,就是程序員可能創(chuàng)建了一個對象,以后一直不再使用這個對象,這個對象卻一直被引用,即這個對象無用但是卻無法被垃圾回收器回收的 ,這就是java中可能出現(xiàn)內(nèi)存泄露的情況,例如,緩存系統(tǒng),我們加載了一個對象放在緩存中(例如放在一個全局map對象中),然后一直不再使用它,這個對象一直被緩存引用,但卻不再被使用。

檢查java中的內(nèi)存泄露,一定要讓程序?qū)⒏鞣N分支情況都完整執(zhí)行到程序結(jié)束,然后看某個對象是否被使用過,如果沒有,則才能判定這個對象屬于內(nèi)存泄露。

如果一個外部類的實例對象的方法返回了一個內(nèi)部類的實例對象,這個內(nèi)部類對象被長期引用了,即使那個外部類實例對象不再被使用,但由于內(nèi)部類持久外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會造成內(nèi)存泄露。

下面內(nèi)容來自于網(wǎng)上(主要特點就是清空堆棧中的某個元素,并不是徹底把它從數(shù)組中拿掉,而是把存儲的總數(shù)減少,本人寫得可以比這個好,在拿掉某個元素時,順便也讓它從數(shù)組中消失,將那個元素所在的位置的值設(shè)置為null即可):

我實在想不到比那個堆棧更經(jīng)典的例子了,以致于我還要引用別人的例子,下面的例子不是我想到的,是書上看到的,當然如果沒有在書上看到,可能過一段時間我自己也想的到,可是那時我說是我自己想到的也沒有人相信的。

public class Stack {

private Object[] elements=new Object[10];

private int size = 0;

public void push(Object e){

ensureCapacity();

elements[size++] = e;

}

public Object pop(){

if( size == 0)

throw new EmptyStackException();

return elements[--size];

}

private void ensureCapacity(){

if(http://emrowgh.com){

Object[] oldElements = elements;

elements = new Object[2 * http://emrowgh.com];

http://emrowgh.com(oldElements,0, elements, 0, size);

}

}

}

上面的原理應(yīng)該很簡單,假如堆棧加了10個元素,然后全部彈出來,雖然堆棧是空的,沒有我們要的東西,但是這是個對象是無法回收的,這個才符合了內(nèi)存泄露的兩個條件:無用,無法回收。

但是就是存在這樣的東西也不一定會導致什么樣的后果,如果這個堆棧用的比較少,也就浪費了幾個K內(nèi)存而已,反正我們的內(nèi)存都上G了,哪里會有什么影響,再說這個東西很快就會被回收的,有什么關(guān)系。下面看兩個例子。

例子 1

public class Bad{

public static Stack s=Stack();

static{

http://emrowgh.com(new Object());

http://emrowgh.com(); //這里有一個對象發(fā)生內(nèi)存泄露 

http://emrowgh.com(new Object()); // 上面的對象可以被回收了,等于是自愈了 

}

}

因為是static,就一直存在到程序退出,但是我們也可以看到它有自愈功能,就是說如果你的Stack最多有100個對象,那么最多也就只有100個對象無法被回收其實這個應(yīng)該很容易理解,Stack內(nèi)部持有100個引用,最壞的情況就是他們都是無用的,因為我們一旦放新的進取,以前的引用自然消失!

內(nèi)存泄露的另外一種情況:當一個對象被存儲進HashSet集合中以后,就不能修改這個對象中的那些參與計算哈希值的字段了,否則,對象修改后的哈希值與最初存儲進HashSet集合中時的哈希值就不同了,在這種情況下,即使在contains方法使用該對象的當前引用作為的參數(shù)去HashSet集合中檢索對象,也將返回找不到對象的結(jié)果,這也會導致無法從HashSet集合中單獨刪除當前對象,造成內(nèi)存泄露。

17、多線程有幾種實現(xiàn)方法?同步有幾種實現(xiàn)方法?

多線程有兩種實現(xiàn)方法,分別是繼承 Thread 類與實現(xiàn) Runnable 接口

同步的實現(xiàn)方面有兩種, 一種同步方法,一種同步代碼! 分別是 synchronized,wait 與 notify

wait(): 使一個線程處于等待狀態(tài),并且釋放所持有的對象的 lock 。

sleep(): 使一個正在運行的線程處于睡眠狀態(tài),是一個靜態(tài)方法,調(diào)用此方法要捕捉InterruptedException 異常。

notify() : 喚醒一個處于等待狀態(tài)的線程,注意的是在調(diào)用此方法的時候,并不能確切的喚醒某一個等待狀態(tài)的線程,而是由 JVM 確定喚醒哪個線程,而且不是按優(yōu)先級。

Allnotity() : 喚醒所有處入等待狀態(tài)的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭

18、sleep() 和 wait() 有什么區(qū)別?

(網(wǎng)上的答案:sleep 是線程類( Thread ) 的方法,導致此線程暫停執(zhí)行 指定時間,給執(zhí)行機會給其他線程,但是監(jiān)控狀態(tài)依然保持,到時后會自動恢復(fù) 。調(diào)用sleep不會釋放對象鎖。 wait 是 Object類 的方法,對此對象調(diào)用wait方法導致本線程放棄對象鎖 ,進入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態(tài)。)

sleep就是正在執(zhí)行的線程主動讓出cpu,cpu去執(zhí)行其他線程,在sleep指定的時間過后,cpu才會回到這個線程上繼續(xù)往下執(zhí)行,如果當前線程進入了同步鎖,sleep方法并不會釋放鎖,即使當前線程使用sleep方法讓出了cpu,但其他被同步鎖擋住了的線程也無法得到執(zhí)行。wait 是指在一個已經(jīng)進入了同步鎖的線程內(nèi),讓自己暫時讓出同步鎖,以便其他正在等待此鎖的線程可以得到同步鎖并運行,只有其他線程調(diào)用了 notify方法 (notify并不釋放鎖,只是告訴調(diào)用過wait方法的線程可以去參與獲得鎖的競爭了,但不是馬上得到鎖,因為鎖還在別人手里,別人還沒釋放。如果notify方法后面的代碼還有很多,需要這些代碼執(zhí)行完后才會釋放鎖,可以在notfiy方法后增加一個等待和一些代碼,看看效果),調(diào)用 wait 方法的線程就會解除wait 狀態(tài)和程序可以再次得到鎖后繼續(xù)向下運行 。對于wait的講解一定要配合例子代碼來說明,才顯得自己真明白。

package http://emrowgh.com

public class MultiThread {

/**

@param args

*/

public static void main(String[] args) {

// TODO Auto-generated method stub

new Thread( new Thread1()).start();

try {

http://emrowgh.com(10);

catch (InterruptedException e) {

// TODO Auto-generated catch block

http://emrowgh.com();

}

new Thread( new Thread2()).start();    

}

private static class Thread1 implements Runnable

{

@Override

public void run() {

// TODO Auto-generated method stub

// 由于這里的 Thread1 和下面的 Thread2 內(nèi)部 run 方法要用同一對象作為監(jiān)視器,我們這里不能用this ,因為在 Thread2 里面的 this 和這個 Thread1 的 this 不是同一個對象。我們用http://emrowgh.com這個字節(jié)碼對象,當前虛擬機里引用這個變量時,指向的都是同一個對象。

synchronized (MultiThread. class ) {

http://emrowgh.com( "enter thread1..." );

http://emrowgh.com( "thread1 is waiting" );

try {

//釋放鎖有兩種方式,第一種方式是程序自然離開監(jiān)視器的范圍,也就是離開了 synchronized 關(guān)鍵字管轄的代碼范圍,另一種方式就是在 synchronized 關(guān)鍵字管轄的代碼內(nèi)部調(diào)用監(jiān)視器對象的 wait 方法。這里,使用 wait 方法釋放鎖。

MultiThread.class .wait();

catch (InterruptedException e) {

// TODO Auto-generated catch block

http://emrowgh.com();

}

http://emrowgh.com( "thread1 is going on..." );

http://emrowgh.com( "thread1 is being over!" );       

}

}

}

private static class Thread2 implements Runnable

{

@Override

public void run() {

// TODO Auto-generated method stub

synchronized (MultiThread. class ) {

http://emrowgh.com( "enter thread2..." );

http://emrowgh.com( "thread2 notify other thread can release wait status.." );

// 由于 notify 方法并不釋放鎖, 即使 thread2 調(diào)用下面的 sleep 方法休息了 10 毫秒,但 thread1仍然不會執(zhí)行,因為 thread2 沒有釋放鎖,所以 Thread1 無法得不到鎖。

MultiThread.class .notify ();

http://emrowgh.com( "thread2 is sleeping ten millisecond..." );

try {

http://emrowgh.com(10);

catch (InterruptedException e) {

// TODO Auto-generated catch block

http://emrowgh.com();

}

http://emrowgh.com( "thread2 is going on..." );

http://emrowgh.com( "thread2 is being over!" );

}

}

}  

}

19、java中有幾種方法可以實現(xiàn)一個線程?用什么關(guān)鍵字修飾同步方法? stop()和suspend()方法為何不推薦使用?

java5以前,有如下兩種:

第一種:

new Thread(){}.start(); 這表示調(diào)用Thread子類對象的run 方法 ,new Thread(){}表示一個Thread的匿名子類的實例對象,子類加上run方法后的代碼如下:

new Thread(){

public void run(){

}

}.start();

第二種:

new Thread(new Runnable(){}).start(); 這表示調(diào)用Thread對象接受的Runnable對象的run方法,new Runnable(){}表示一個Runnable的匿名子類的實例對象,runnable的子類加上run方法后的代碼如下:

new Thread(new Runnable(){

public void run(){

}    

}

).start();

從java5開始,還有如下一些線程池創(chuàng)建多線程 的方式:

ExecutorService pool = http://emrowgh.com(3)

for(int i=0;i<10;i++)

{

http://emrowgh.com(new Runable(){public void run(){}});

}

http://emrowgh.com().execute(new Runable(){public void run(){}});

http://emrowgh.com().execute(new Runable(){public void run(){}});

有兩種實現(xiàn)方法,分別使用new Thread()和new Thread(runnable)形式,第一種直接調(diào)用thread的run方法,所以,我們往往使用Thread子類,即new SubThread()。第二種調(diào)用runnable的run方法。

有兩種實現(xiàn)方法,分別是繼承 Thread 類與實現(xiàn) Runnable 接口

用 synchronized 關(guān)鍵字修飾 同步方法

反對使用stop(),是因為它不安全。 它會解除由線程獲取的所有鎖定 ,而且如果對象處于一種不連貫狀態(tài),那么其他線程能在那種狀態(tài)下檢查和修改它們。結(jié)果很難檢查出真正的問題所在。suspend()方法容易發(fā)生死鎖 。調(diào)用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復(fù)運行。對任何線程來說,如果它們想恢復(fù)目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應(yīng)該使用suspend(),而應(yīng)在自己的Thread類中置入一個標志,指出線程應(yīng)該活動還是掛起。若標志指出線程應(yīng)該掛起,便用wait()命其進入等待狀態(tài)。若標志指出線程應(yīng)當恢復(fù),則用一個notify()重新啟動線程。

20、Java中的異常處理機制的簡單原理和應(yīng)用。

異常是指java程序運行時(非編譯)所發(fā)生的非正常情況或錯誤,與現(xiàn)實生活中的事件很相似,現(xiàn)實生活中的事件可以包含事件發(fā)生的時間、地點、人物、情節(jié)等信息,可以用一個對象來表示,Java使用面向?qū)ο蟮姆绞絹硖幚懋惓#殉绦蛑邪l(fā)生的每個異常也都分別封裝到一個對象來表示的,該對象中包含有異常的信息 。

Java對異常進行了分類,不同類型的異常分別用不同的Java類表示,所有異常的根類為http://emrowgh.com,Throwable下面又派生了兩個子類: Error 和 Exception ,Error 表示應(yīng)用程序本身無法克服和恢復(fù)的一種嚴重問題,程序只有死的份了,例如,說內(nèi)存溢出和線程死鎖等系統(tǒng)問題。Exception表示程序還能夠克服和恢復(fù)的問題,其中又分為系統(tǒng)異常和普通異常,系統(tǒng)異常是軟件本身缺陷所導致的問題,也就是軟件開發(fā)人員考慮不周所導致的問題,軟件使用者無法克服和恢復(fù)這種問題,但在這種問題下還可以讓軟件系統(tǒng)繼續(xù)運行或者讓軟件死掉,例如,數(shù)組腳本越界(ArrayIndexOutOfBoundsException),空指針異常(NullPointerException)、類轉(zhuǎn)換異常(ClassCastException);普通異常是運行環(huán)境的變化或異常所導致的問題,是用戶能夠克服的問題,例如,網(wǎng)絡(luò)斷線,硬盤空間不夠,發(fā)生這樣的異常后,程序不應(yīng)該死掉。

java為系統(tǒng)異常和普通異常提供了不同的解決方案,編譯器強制普通異常必須try..catch處理或用throws聲明繼續(xù)拋給上層調(diào)用方法處理,所以普通異常也稱為checked異常,而系統(tǒng)異?梢蕴幚硪部梢圆惶幚,所以,編譯器不強制用try..catch處理或用throws聲明,所以系統(tǒng)異常也稱為unchecked異常。

21、final, finally, finalize的區(qū)別。

final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。

內(nèi)部類要訪問局部變量,局部變量必須定義成final類型,例如,一段代碼……

finally是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。

finalize是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等。JVM不保證此方法總被調(diào)用

22、數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法?

數(shù)組沒有l(wèi)ength()這個方法,有l(wèi)ength的屬性。String有l(wèi)ength()這個方法。

http://emrowgh.com與StringBuilder的區(qū)別

StringBuffer和StringBuilder類都表示內(nèi)容可以被修改的字符串 ,StringBuilder是線程不安全的 ,運行效率高,如果一個字符串變量是在方法里面定義,這種情況只可能有一個線程訪問它 ,不存在不安全的因素了,則用 StringBuilder 。如果要在類里面定義成員變量,并且這個類的實例對象會在多線程 環(huán)境下使用,那么最好用 StringBuffer 。

24、String 和StringBuffer的區(qū)別

String類表示內(nèi)容不可改變 的字符串。而StringBuffer類表示內(nèi)容可以被修改 的字符串

25、Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實現(xiàn))interf-ace(接口)?

可以繼承其他類或?qū)崿F(xiàn)其他接口。不僅是可以,而是必須 !

http://emrowgh.com單例模式

Java中 單例模式是一種常見的設(shè)計模式,

單例模式分三種:懶漢式單例、餓漢式單例、登記式單例

單例模式有一下特點:

1、單例類只能有一個實例。

2、單例類必須自己自己創(chuàng)建自己的唯一實例。

3、單例類必須給所有其他對象提供這一實例。

27、說出一些數(shù)據(jù)庫優(yōu)化方面的經(jīng)驗?

用PreparedStatement 一般來說比Statement性能高:一個sql 發(fā)給服務(wù)器去執(zhí)行,涉及步驟:語法檢查、語義分析, 編譯,緩存

“inert into user values(1,1,1)”-à二進制

“inert into user values(2,2,2)”-à二進制

“inert into user values(?,?,?)”-à二進制

有外鍵約束會影響插入和刪除性能,如果程序能夠保證數(shù)據(jù)的完整性,那在設(shè)計數(shù)據(jù)庫時就去掉外鍵。(比喻:就好比免檢產(chǎn)品,就是為了提高效率,充分相信產(chǎn)品的制造商)

(對于hibernate來說,就應(yīng)該有一個變化:empleyee->Deptment對象,現(xiàn)在設(shè)計時就成了employeeàdeptid)

看mysql幫助文檔子查詢章節(jié)的最后部分,例如,根據(jù)掃描的原理,下面的子查詢語句要比第二條關(guān)聯(lián)查詢的效率高:

1.  select http://emrowgh.com(select id from employee where name='zxx');

2.   select http://emrowgh.com

http://emrowgh.com'zxx';

表中允許適當冗余,譬如,主題帖的回復(fù)數(shù)量和最后回復(fù)時間等

將姓名和密碼單獨從用戶表中獨立出來。這可以是非常好的一對一的案例喲!

sql語句全部大寫,特別是列名和表名都大寫。特別是sql命令的緩存功能,更加需要統(tǒng)一大小寫,sql語句à發(fā)給oracle服務(wù)器à語法檢查和編譯成為內(nèi)部指令à緩存和執(zhí)行指令。根據(jù)緩存的特點,不要拼湊條件,而是用?和PreparedStatment

還有索引對查詢性能的改進也是值得關(guān)注的。

28、XML文檔定義有幾種形式?它們之間有何本質(zhì)區(qū)別?解析XML文檔有哪幾種方式?

a: 兩種形式 dtd  schema, b: 本質(zhì)區(qū)別 :schema 本身是 xml 的,可以被 XML 解析器解析 ( 這也是從DTD 上發(fā)展 schema 的根本目的 ) , c: 有 DOM,SAX,STAX 等

DOM:處理大型文件時其性能下降的非常厲害。這個問題是由 DOM 的樹結(jié)構(gòu)所造成的,這種結(jié)構(gòu)占用的內(nèi)存較多,而且 DOM 必須在解析文件之前把整個文檔裝入內(nèi)存 , 適合對 XML 的隨機訪問

SAX: 不現(xiàn)于 DOM,SAX 是事件驅(qū)動型的 XML 解析方式。它順序讀取 XML 文件,不需要一次全部裝載整個文件。當遇到像文件開頭,文檔結(jié)束,或者標簽開頭與標簽結(jié)束時,它會觸發(fā)一個事件,用戶通過在其回調(diào)事件中寫入處理代碼來處理 XML 文件,適合對 XML 的順序訪問

STAX:Streaming API for XML (StAX)

29、hibernate中的update()和saveOrUpdate()的區(qū)別,session的load()和get()的區(qū)別。

update針對的是已存在的實體對象

saveOrUpdate()對象存在與否都不會有任何影響

session的load()和get()的區(qū)別

load是只在緩存中加載數(shù)據(jù)

get是先緩存中查找或者緩存中沒有到數(shù)據(jù)庫中查找

30. How to set many-to-many relationship in Hibernate?

Hibernate中怎樣實現(xiàn)類之間的關(guān)系?(如:一對多、多對多的關(guān)系 )

類與類之間的關(guān)系主要體現(xiàn)在表與表之間的關(guān)系進行操作,它們都市對對象進行操作,我們程序中把所有的表與類都映射在一起,它們通過配置文件中的many-to-one、one-to-many、many-many

31如何優(yōu)化Hibernate?

* 使用雙向一對多關(guān)聯(lián),不使用單向一對多

* 靈活使用單向一對多關(guān)聯(lián)

* 不用一對一,用多對一取代

* 配置對象緩存,不使用集合緩存

* 一對多集合使用Bag,多對多集合使用Set

* 繼承類使用顯式多態(tài)

* 表字段要少,表關(guān)聯(lián)不要怕多,有二級緩存撐腰