1、一個".java"源文件裏可否夠包含多個類(不是內部類)?有什麼限制?.....2html
3、說說&和&&的差異。......................................................................................2java
4、在JAVA中怎樣跳出當前的多重嵌套循環?...................................................2node
5、switch語句是否能做用在byte上,是否能做用在long上,是否能做用在String上?mysql
...2c++
6、short s1 =1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?git
爲何?............................................2
9、請設計一個一百億的計算器..........................................................................2
10、使用finalkeyword修飾一個變量時,是引用不能變,仍是引用的對象不能變?2
11、"=="和equals方法到底有什麼差異?...........................................................2
12、靜態變量和實例變量的差異?.....................................................................2
13、可否夠從一個static方法內部發出對非static方法的調用?........................2
15、Math.round(11.5)等於多少?Math.round(-11.5)等於多少?...............................2
.......................................................................2
17、請說出做用域public,private,protected,以及不寫時的差異.......................2
19、構造器Constructor是否可被override?..........................................................2
20、接口是否可繼承接口?抽象類是否可實現(implements)接口?抽象類是否可繼承詳細類(concreteclass)?
抽象類中可否夠有靜態的main方法?.......................................................................2
21、寫clone()方法時。一般都有一行代碼,是什麼?.........................................2
22、面向對象的特徵有哪些方面.........................................................................2
23、java中實現多態的機制是什麼?..................................................................2
24、abstractclass和interface有什麼差異?...........................................................2
25、abstract的method是否可同一時候是static,是否可同一時候是native。是否可同一時候是synchronized?
2
26、什麼是內部類?StaticNested Class 和 Inner Class的不一樣。..........................2
27、內部類可以引用它的包括類的成員嗎?有沒有什麼限制?...........................2
28、AnonymousInner Class (匿名內部類)可否夠extends(繼承)其餘類,可否夠implements(實現)interface(接口)?
29、super.getClass()方法調用.....................................................................2
.....................................................................2
31、String s = "Hello";s = s + " world!";這兩行代碼運行後,原始的String對象中的內容究竟變了沒有? 2
..............................................................................2
33、String s =new String("xyz");建立了幾個String Object?兩者之間有什麼差異? 2
34、String和StringBuffer的差異.......................................................................2
...........................................2
36、數組有沒有length()這種方法?String有沒有length()這種方法?...................2
37、如下這條語句一共建立了多少個對象:Strings="a"+"b"+"c"+"d";.................2
38、try {}裏有一個return語句,那麼緊跟在這個try後的finally{}裏的code會不會被運行。何時被運行,在return前仍是後?
.................................................................................................2
39、如下的程序代碼輸出的結果是多少?...........................................................2
40、final,finally, finalize的差異。......................................................................2
41、執行時異常與通常異常有何異同?..............................................................2
42、error和exception有什麼差異?.....................................................................2
................................................2
44、請寫出你最多見到的5個runtimeexception。...............................................2
.....................................................................2
48、同步和異步有何異同,在什麼狀況下分別使用他們?舉例說明。
49.如下兩個方法同步嗎?(本身發明)...........................................................2
.............................................2
51、啓動一個線程是用run()仍是start()?............................................................2
52、當一個線程進入一個對象的一個synchronized方法後,其餘線程是否可進入此對象的其餘方法? 2
53、線程的基本概念、線程的基本狀態以及狀態之間的關係...............................2
54、簡述synchronized和java.util.concurrent.locks.Lock的異同?.......................2
55、設計4個線程,當中兩個線程每次對j添加1,另外兩個線程對j每次下降1。寫出程序。 2
57、介紹Collection框架的結構..........................................................................2
58、Collection框架中實現比較要實現什麼接口..................................................2
59、ArrayList和Vector的差異............................................................................2
60、HashMap和Hashtable的差異.......................................................................2
......................................................................................2
62、List, Set,Map是否繼承自Collection接口?
....................................................2
63、List、Map、Set三個接口,存取元素時,各有什麼特色?............................2
64、說出ArrayList,Vector,LinkedList的存儲性能和特性......................................2
65、去掉一個Vector集合中反覆的元素..............................................................2
66、Collection和 Collections的差異。...............................................................2
67、Set裏的元素是不能反覆的,那麼用什麼方法來區分反覆與否呢?是用==仍是equals()?
68、你所知道的集合類都有哪些?主要方法?....................................................2
69、兩個對象值一樣(x.equals(y)== true)。但卻可有不一樣的hash code,這句話對不正確? 2
71、說出一些常用的類,包。接口,請各舉5個................................................2
72、java中有幾種類型的流?JDK爲每種類型的流提供了一些抽象類以供繼承,請說出他們各自是哪些類? 2
73、字節流與字符流的差異................................................................................2
74、什麼是java序列化,怎樣實現java序列化?或者請解釋Serializable接口的做用。 2
75、描寫敘述一下JVM載入class文件的原理機制?...................................................2
76、heap和stack有什麼差異。..........................................................................2
爲何要有GC?.......................................................................2
並考慮2種回收機制。.........................................2
.....................................................................................2
....................................................2
82、能不能本身寫個類,也叫java.lang.String?.................................................2
2、編寫一個程序,將d:\java文件夾下的所有.java文件拷貝到d:\jad文件夾下,並將原來文件的擴展名從.java改成.jad。
4、有一個字符串。當中包括中文字符、英文字符和數字字符。請統計和打印出各個字符的個數。
5、說明生活中遇到的二叉樹,用java實現二叉樹..............................................2
6、從相似例如如下的文本文件裏讀取出所有的姓名。並打印出反覆的姓名和反覆的次數,並按反覆次數排序: 2
................................................................................2
用JAVA實現一個高速排序。.....................2
11、有數組a[n]。用java代碼將數組元素順序顛倒.............................................2
12.金額轉換。阿拉伯數字的金額轉換成中國傳統的形式如:(¥1011)->(一千零一拾一元整)輸出。
1.推斷第二個日期比第一個日期大....................................................................2
3、HTML的 form 提交以前怎樣驗證數值文本框的內容全部爲數字?不然的話提示用戶並終止提交? 2
4、請寫出用於校驗HTML文本框中輸入的內容全部爲數字的javascript代碼......2
5、說說你用過那些ajax技術和框架。說說它們的差異.......................................2
2、HTTP請求的GET與POST方式的差異.........................................................2
3、解釋一下什麼是servlet;.................................................................................2
4、說一說Servlet的生命週期?...........................................................................2
6、SERVLET API中forward()與redirect()的差異?...........................................2
7、什麼狀況下調用doGet()和doPost()?............................................................2
8、Request對象的主要方法:.............................................................................2
9、forward和redirect的差異.............................................................................2
10、request.getAttribute()和 request.getParameter() 有何差異?............................2
11.jsp有哪些內置對象?做用各自是什麼?分別有什麼方法?..............................2
12.jsp有哪些動做?做用各自是什麼?..................................................................2
14.JSP中動態INCLUDE與靜態INCLUDE的差異?.........................................2
........................................................2
16、頁面間對象傳遞的方法................................................................................2
17、JSP和Servlet有哪些一樣點和不一樣點,他們之間的聯繫是什麼?................2
........................................2
1、用兩種方式依據部門號從高到低,工資從低到高列出每個員工的信息。........2
2、列出各個部門中工資高於本部門的平均工資的員工數和部門號,並按部門號排序 2
....................................................2
4、數據庫三範式是什麼?...................................................................................2
5、說出一些數據庫優化方面的經驗?..................................................................2
6、union和union all有什麼不一樣?.......................................................................2
8.用一條SQL語句查詢出每門課都大於80分的學生姓名..................................2
9.所有部門之間的比賽組合................................................................................2
10.每個月份的發生額都比101科目多的科目......................................................2
11.統計每一年每個月的信息......................................................................................2
12.顯示文章標題,發帖人、最後回覆時間..........................................................2
13.刪除除了id號不一樣,其它都一樣的學生冗餘信息.............................................2
14.航空網的幾個航班查詢題:...........................................................................2
15.查出比經理薪水還高的員工信息:.................................................................2
16、求出小於45歲的各個老師所帶的大於12歲的學生人數...............................2
17.求出發帖最多的人:......................................................................................2
18、一個用戶表中有一個積分字段,假如數據庫中有100多萬個用戶。若要在每一年第一天凌晨將積分清零,你將考慮什麼,你將想什麼辦法解決?
.......................................................................2
19、一個用戶具備多個角色,請查詢出該表中具備該用戶的所有角色的其它用戶。
21、註冊Jdbc驅動程序的三種方式....................................................................2
22、用JDBC怎樣調用存儲過程.........................................................................2
23、JDBC中的PreparedStatement相比Statement的優勢.....................................2
24.寫一個用jdbc鏈接並訪問oracle數據的程序代碼..........................................2
爲何要用?..............................................................2
26、大數據量下的分頁解決方法。.....................................................................2
27、用 JDBC 查詢學生成績單,把主要代碼寫出來(考試機率極大)................2
28、這段代碼有什麼不足之處?...........................................................................2
29、說出數據鏈接池的工做機制是什麼?.............................................................2
和 JDBC 有何不同?.................................................2
1、xml有哪些解析技術?差異是什麼?.................................................................2
2、你在項目中用到了xml技術的哪些方面?怎樣實現的?....................................2
3、用jdom解析xml文件時怎樣解決中文問題?怎樣解析?...................................2
4、編程用JAVA解析XML的方式......................................................................2
5、XML文檔定義有幾種形式?它們之間有何本質差異?解析XML文檔有哪幾種方式? 2
1、談談你對Struts的理解。...............................................................................2
2、談談你對Hibernate的理解。.........................................................................2
...............................................................................................2
4、你對Spring的理解。....................................................................................2
5、談談Struts中的Actionservlet。.....................................................................2
6、Struts優缺點 長處: 1.實現MVC模式,結構清晰,使開發人員僅僅關注業務邏輯的實現. 2
7、STRUTS的應用(如STRUTS架構).................................................................2
8、說說struts1與struts2的差異。......................................................................2
9、hibernate中的update()和saveOrUpdate()的差異,session的load()和get()的差異。 2
11、iBatis與Hibernate有什麼不一樣?....................................................................2
12、寫Hibernate的一對多和多對一雙向關聯的orm配置?...................................2
9、hibernate的inverse屬性的做用?.....................................................................2
13、在DAO中怎樣體現DAO設計模式?............................................................2
14、spring+Hibernate中託付方案怎麼配置?........................................................2
........................................................2
17.介紹一下Hibernate的二級緩存......................................................................2
給一個 Bean的 message屬性,字符串類型,注入值爲 "Hello"的 XML配置文件該怎麼寫?
................................................................................................2
.................................................................................................2
20、什麼是spring的IOC AOP.........................................................................2
21、STRUTS的工做流程!................................................................................2
22、spring與EJB的差異!。............................................................................2
2、j2ee常用的設計模式?說明工廠模式。.........................................................2
...............................................2
1、BS與CS的聯繫與差異。..............................................................................2
2、應用server與WEBSERVER的差異?..........................................................2
3、應用server有那些?.....................................................................................2
5、J2EE是技術仍是平臺仍是框架?什麼是J2EE.............................................2
6、請對下面在J2EE中常用的名詞進行解釋(或簡單描寫敘述)...................................2
7、怎樣給weblogic指定大小的內存?..................................................................2
8、怎樣設定的weblogic的熱啓動模式(開發模式)與產品公佈模式?.....................2
9、怎樣啓動時不需輸入username與password?..............................................................2
12、在weblogic中公佈ejb需涉及到哪些配置文件..............................................2
13、怎樣在weblogic中進行ssl配置與client的認證配置或說說j2ee(標準)進行ssl的配置? 2
14、怎樣查看在weblogic中已經公佈的EJB?......................................................2
1、EJB是基於哪些技術實現的?並說出SessionBean和EntityBean的差異,StatefulBean和StatelessBean的差異。
2、簡要講一下 EJB 的 7 個Transaction Level?
.................................................2
3、EJB與JAVA BEAN的差異?........................................................................2
4、EJB包含(SessionBean,EntityBean)說出他們的生命週期,及怎樣管理事務的? 2
5、EJB容器提供的服務.....................................................................................2
8、客服端調用EJB對象的幾個基本步驟............................................................2
2、CORBA是什麼?用途是什麼?.........................................................................2
4、LINUX下線程。GDI類的解釋。..................................................................2
6、四種會話跟蹤技術........................................................................................2
7、簡述邏輯操做(&,|,^)與條件操做(&&,||)的差異。............................................2
1、請用英文簡介一下本身..........................................................................2
2、請把http://tomcat.apache.org/ 首頁的這一段話用中文翻譯一下?
3、美資軟件公司JAVAproject師電話面試題目......................................................2
這套面試題主要目的是幫助那些尚未java軟件開發實際工做經驗,而正在努力尋找java軟件開發工做的朋友在筆試時更好地贏得筆試和麪試。由於這套面試題涉及的範圍很是泛。很是廣,很是雜,你們不可能一天兩天就看完和學完這套面試寶典,即便你已經學過了有關的技術。那麼至少也需要一個月的時間才幹消化和掌握這套面試寶典,因此,你們應該早做準備。從拿到這套面試寶典之日起。就要堅持在天天閒暇之餘學習當中幾道題目,日積月累,等到出去面試時,一切都水到渠成,面試時就天然會遊刃有餘了。
答題時。先答是什麼,再答有什麼做用和要注意什麼(這部分最重要,展示本身的心得)
答案的段落分別,井井有條。條理清晰都很重要,從這些表面的東西也可以看出一我的的習慣、辦事風格、條理等。
要講你作出答案的思路過程。或者說你記住答案的思想都寫下來。把答題想着是辯論賽。
答題就是給別人講道理、擺事實。答題不侷限於什麼格式和形式,就是要將本身的學識展示出來!
別因爲人家題目原本就模棱兩可。你就內心膽怯和沒底氣了,不敢回答了。
你要大膽地指出對方題目很是模糊和你的觀點。不要把面試官想得有多高。事實上他和你就是差點兒相同的,你想一想。假設他把你招進去了,大家之後就是同事了,可不是差點兒相同的嗎?
關於就業薪水。假設你是應屆生。那不能要高工資,比如大餅的故事,沒有文憑還想拿高工資。就去中關村缺什麼補什麼吧!
少數人基礎確實很是好,在校期間確實又作過一些項目,那仍然是可以要到相對高的工資的。
1. Java基礎部分
基礎部分的順序:基本的語法。類相關的語法。內部類的語法。繼承相關的語法,異常的語法。線程的語法。集合的語法,io的語法。虛擬機方面的語法。
1、一個".java"源文件裏可否夠包含多個類(不是內部類)?有什麼限制?
可以有多個類,但僅僅能有一個public的類。並且public的類名必須與文件名稱相一致。
2、Java有沒有goto?
java中的保留字,現在沒有在java中使用。
3、說說&和&&的差異。
&和&&都可以用做邏輯與的運算符,表示邏輯與(and),當運算符兩邊的表達式的結果都爲true時,整個運算結果才爲true。不然,僅僅要有一方爲false,則結果爲false。
&&還具備短路的功能,即假設第一個表達式爲false,則再也不計算第二個表達式,好比,對於if(str != null&& !str.equals(「」))表達式,當str爲null時。後面的表達式不會運行,因此不會出現NullPointerException假設將&&改成&,則會拋出NullPointerException異常。If(x==33 &++y>0) y會增加。If(x==33 && ++y>0)不會增加
&還可以用做位運算符,當&操做符兩邊的表達式不是boolean類型時,&表示按位與操做,咱們一般使用0x0f來與一個整數進行&運算。來獲取該整數的最低4個bit位,好比,0x31 & 0x0f的結果爲0x01。
備註:這道題先說二者的共同點。再說出&&和&的特殊之處,並列舉一些經典的樣例來代表本身理解透徹深刻、實際經驗豐富。
f
4、在JAVA中怎樣跳出當前的多重嵌套循環?
在Java中,要想跳出多重循環,可以在外面的循環語句前定義一個標號。而後在裏層循環體的代碼中使用帶有標號的break語句,就能夠跳出外層循環。
好比,
ok:
for(int i=0;i<10;i++) {
for(int j=0;j<10;j++) {
System.out.println(「i=」 + i + 「,j=」 + j);
if(j == 5) break ok;
}
}
另外,我我的一般並不使用標號這樣的方式,而是讓外層的循環條件表達式的結果可以受到裏層循環體代碼的控制。好比,要在二維數組中查找到某個數字。
int arr[][] ={{1,2,3},{4,5,6,7},{9}};
boolean found = false;
for(int i=0;i<arr.length&& !found;i++) {
for(int j=0;j<arr[i].length;j++){
System.out.println(「i=」 + i + 「,j=」 + j);
if(arr[i][j] ==5) {
found = true;
break;
}
}
}
5、switch語句是否能做用在byte上,是否能做用在long上,是否能做用在String上?
在switch(expr1)中,expr1僅僅能是一個整數表達式或者枚舉常量(更大字體),整數表達式可以是int基本類型或Integer包裝類型。由於。byte,short,char都可以隱含轉換爲int,因此。這些類型以及這些類型的包裝類型也是可以的。
顯然,long和String類型都不符合switch的語法規定。並且不能被隱式轉換成int類型,因此。它們不能做用於swtich語句中。
6、short s1 = 1; s1 = s1 + 1;有什麼錯? short s1 = 1; s1 += 1;有什麼錯?
對於short s1 = 1; s1 = s1 + 1;由於s1+1運算時會本身主動提高表達式的類型,因此結果是int型,再賦值給short類型s1時。編譯器將報告需要強制轉換類型的錯誤。
對於short s1 = 1; s1 += 1;由於 +=是java語言規定的運算符。java編譯器會對它進行特殊處理,所以可以正確編譯。
7、char型變量中能不能存貯一箇中文漢字?
爲何?
char型變量是用來存儲Unicode編碼的字符的,unicode編碼字符集中包括了漢字。因此,char型變量中固然可以存儲漢字啦。只是,假設某個特殊的漢字沒有被包括在unicode編碼字符集中,那麼,這個char型變量中就不能存儲這個特殊漢字。
補充說明:unicode編碼佔用兩個字節。因此。char類型的變量也是佔用兩個字節。
備註:後面一部分回答儘管不是在正面回答題目。但是,爲了展示本身的學識和表現本身對問題理解的透徹深刻。可以回答一些相關的知識,作到知無不言,言無不盡。
8、用最有效率的方法算出2乘以8等於幾?
2 << 3,
因爲將一個數左移n位,就至關於乘以了2的n次方,那麼,一個數乘以8僅僅要將其左移3位就能夠,而位運算cpu直接支持的。效率最高。因此,2乘以8等於幾的最效率的方法是2 << 3。
9、請設計一個一百億的計算器
首先要明確這道題目的考查點是什麼。一是你們首先要對計算機原理的底層細節要清楚、要知道加減法的位運算原理和知道計算機中的算術運算會發生越界的狀況,二是要具有必定的面向對象的設計思想。
首先。計算機中用固定數量的幾個字節來存儲的數值,因此計算機中能夠表示的數值是有必定的範圍的,爲了便於解說和理解,咱們先以byte類型的整數爲例,它用1個字節進行存儲。表示的最大數值範圍爲-128到+127。-1在內存中相應的二進制數據爲11111111。假設兩個-1相加,不考慮Java運算時的類型提高,運算後會產生進位,二進制結果爲1,11111110,由於進位後超過了byte類型的存儲空間。因此進位部分被捨棄。即終於的結果爲11111110,也就是-2。這正好利用溢位的方式實現了負數的運算。
-128在內存中相應的二進制數據爲10000000,假設兩個-128相加。不考慮Java運算時的類型提高。運算後會產生進位。二進制結果爲1,00000000,由於進位後超過了byte類型的存儲空間,因此進位部分被捨棄,即終於的結果爲00000000。也就是0,這種結果顯然不是咱們指望的,這說明計算機中的算術運算是會發生越界狀況的。兩個數值的運算結果不能超過計算機中的該類型的數值範圍。
由於Java中涉及表達式運算時的類型本身主動提高。咱們沒法用byte類型來作演示這種問題和現象的實驗,你們能夠用如下一個使用整數作實驗的樣例程序體驗一下:
int a = Integer.MAX_VALUE;
int b = Integer.MAX_VALUE;
int sum = a + b;
System.out.println(「a=」+a+」,b=」+b+」,sum=」+sum);
先不考慮long類型。由於int的正數範圍爲2的31次方,表示的最大數值約等於2*1000*1000*1000,也就是20億的大小。因此。要實現一個一百億的計算器。咱們得本身設計一個類可以用於表示很是大的整數,並且提供了與另一個整數進行加減乘除的功能。大概功能例如如下:
()這個類內部有兩個成員變量,一個表示符號。還有一個用字節數組表示數值的二進制數
()有一個構造方法,把一個包括有多位數值的字符串轉換到內部的符號和字節數組中
()提供加減乘除的功能
public class BigInteger{
int sign;
byte[] val;
public Biginteger(String val) {
sign = ;
val = ;
}
public BigInteger add(BigInteger other) {
}
public BigInteger subtract(BigInteger other) {
}
public BigInteger multiply(BigInteger other){
}
public BigInteger divide(BigInteger other){
}
}
備註:要想寫出這個類的完整代碼。是很是複雜的,假設有興趣的話,可以參看jdk中自帶的java.math.BigInteger類的源代碼。面試的人也知道誰都不可能在短期內寫出這個類的完整代碼的。他要的是你是否有這方面的概念和意識,他最重要的仍是考查你的能力,因此,你不要因爲本身沒法寫出完整的終於結果就放棄答這道題,你要作的就是你比別人寫得多,證實你比別人強,你有這方面的思想意識就可以了,畢竟別人可能連題目的意思都看不懂,什麼都沒寫,你要勇於答這道題,即便僅僅答了一部分,那也與那些什麼都不懂的人差異出來,拉開了距離,算是矮子中的高個,機會固然就屬於你了。另外,答案中的框架代碼也很是重要。體現了一些面向對象設計的功底,特別是當中的方法命名很是專業,用的英文單詞很是精準。這也是能力、經驗、專業性、英語水平等多個方面的體現,會給人留下很是好的印象,在編程能力和其它方面條件差點兒相同的狀況下。英語好除了可以使你得到不少其它機會外,薪水可以高出一千元。
10、使用finalkeyword修飾一個變量時,是引用不能變,仍是引用的對象不能變?
使用finalkeyword修飾一個變量時,是指引用變量不能變,引用變量所指向的對象中的內容仍是可以改變的。好比,對於例如如下語句:
final StringBuffer a=new StringBuffer("immutable");
運行例如如下語句將報告編譯期錯誤:
a=new StringBuffer("");
但是。運行例如如下語句則可以經過編譯:
a.append(" broken!");
有人在定義方法的參數時,可能想採用例如如下形式來阻止方法內部改動傳進來的參數對象:
public void method(final StringBuffer param){
}
實際上,這是辦不到的。在該方法內部仍然可以添加例如如下代碼來改動參數對象:
param.append("a");
11、"=="和equals方法到底有什麼差異?
(單獨把一個東西說清楚。而後再說清楚還有一個。這樣,它們的差異天然就出來了,混在一塊兒說,則很是難說清楚)
==操做符專門用來比較兩個變量的值是否相等。也就是用於比較變量所相應的內存中所存儲的數值是否一樣,要比較兩個基本類型的數據或兩個引用變量是否相等,僅僅能用==操做符。
假設一個變量指向的數據是對象類型的,那麼,這時候涉及了兩塊內存,對象自己佔用一塊內存(堆內存),變量也佔用一塊內存,好比Objet obj = newObject();變量obj是一個內存,new Object()是還有一個內存,此時,變量obj所相應的內存中存儲的數值就是對象佔用的那塊內存的首地址。對於指向對象類型的變量,假設要比較兩個變量是否指向同一個對象,即要看這兩個變量所相應的內存中的數值是否相等,這時候就需要用==操做符進行比較。
equals方法是用於比較兩個獨立對象的內容是否一樣,就比如去比較兩我的的長相是否一樣。它比較的兩個對象是獨立的。
好比,對於如下的代碼:
String a=new String("foo");
String b=new String("foo");
兩條new語句建立了兩個對象。而後用a/b這兩個變量分別指向了當中一個對象,這是兩個不一樣的對象,它們的首地址是不一樣的,即a和b中存儲的數值是不一樣樣的,因此,表達式a==b將返回false。而這兩個對象中的內容是一樣的。因此,表達式a.equals(b)將返回true。
在實際開發中,咱們經常要比較傳遞進行來的字符串內容是否等,好比。String input = …;input.equals(「quit」),不少人稍不注意就使用==進行比較了。這是錯誤的。隨便從網上找幾個項目實戰的教學視頻看看。裏面就有大量這種錯誤。記住。字符串的比較基本上都是使用equals方法。
假設一個類沒有自定義equals方法,那麼它將繼承Object類的equals方法。Object類的equals方法的實現代碼例如如下:
boolean equals(Object o){
return this==o;
}
這說明,假設一個類沒有自定義equals方法。它默認的equals方法(從Object類繼承的)就是使用==操做符,也是在比較兩個變量指向的對象是不是同一對象,這時候使用equals和使用==會獲得一樣的結果,假設比較的是兩個獨立的對象則總返回false。假設你編寫的類但願能夠比較該類建立的兩個實例對象的內容是否一樣,那麼你必須覆蓋equals方法,由你本身寫代碼來決定在什麼狀況就能夠以爲兩個對象的內容是一樣的。
12、靜態變量和實例變量的差異?
在語法定義上的差異:靜態變量前要加statickeyword,而實例變量前則不加。
在程序執行時的差異:實例變量屬於某個對象的屬性,必須建立了實例對象。當中的實例變量纔會被分配空間,才幹使用這個實例變量。靜態變量不屬於某個實例對象,而是屬於類。因此也稱爲類變量。僅僅要程序載入了類的字節碼。不用建立不論什麼實例對象,靜態變量就會被分配空間。靜態變量就可以被使用了。總之,實例變量必須建立對象後才幹夠經過這個對象來使用,靜態變量則可以直接使用類名來引用。
好比。對於如下的程序,無論建立多少個實例對象。永遠都僅僅分配了一個staticVar變量,並且每建立一個實例對象,這個staticVar就會加1。但是。每建立一個實例對象。就會分配一個instanceVar。就能夠能分配多個instanceVar,並且每個instanceVar的值都僅僅自加了1次。
public class VariantTest{
public static int staticVar = 0;
public int instanceVar = 0;
public VariantTest(){
staticVar++;
instanceVar++;
System.out.println(「staticVar=」 + staticVar + 」,instanceVar=」+ instanceVar);
}
}
備註:這個解答除了說清楚二者的差異外。最後還用一個詳細的應用樣例來講明二者的差別,體現了本身有很是好的講解問題和設計案例的能力,思惟敏捷。超過通常程序猿,有寫做能力!
13、可否夠從一個static方法內部發出對非static方法的調用?
不可以。
因爲非static方法是要與對象關聯在一塊兒的。必須建立一個對象後,才幹夠在該對象上進行方法調用,而static方法調用時不需要建立對象。可以直接調用。也就是說,當一個static方法被調用時。可能尚未建立不論什麼實例對象,假設從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪一個對象上的呢?這個邏輯沒法成立,因此,一個static方法內部發出對非static方法的調用。
14、Integer與int的差異
int是java提供的8種原始數據類型之中的一個。Java爲每個原始類型提供了封裝類,Integer是java爲int提供的封裝類。int的默認值爲0,而Integer的默認值爲null,即Integer可以區分出未賦值和值爲0的差異,int則沒法表達出未賦值的狀況。好比,要想表達出沒有參加考試和考試成績爲0的差異。則僅僅能使用Integer。在JSP開發中。Integer的默以爲null,因此用el表達式在文本框中顯示時,值爲空白字符串。而int默認的默認值爲0,因此用el表達式在文本框中顯示時。結果爲0,因此,int不適合做爲web層的表單數據的類型。
在Hibernate中。假設將OID定義爲Integer類型。那麼Hibernate就可以依據其值是否爲null而推斷一個對象是不是暫時的。假設將OID定義爲了int類型,還需要在hbm映射文件裏設置其unsaved-value屬性爲0。
另外,Integer提供了多個與整數相關的操做方法。好比,將一個字符串轉換成整數,Integer中還定義了表示整數的最大值和最小值的常量。
15、Math.round(11.5)等於多少?
Math.round(-11.5)等於多少?
Math類中提供了三個與取整有關的方法:ceil、floor、round,這些方法的做用與它們的英文名稱的含義相相應。好比,ceil的英文意義是天花板,該方法就表示向上取整,Math.ceil(11.3)的結果爲12,Math.ceil(-11.3)的結果是-11。floor的英文意義是地板,該方法就表示向下取整,Math.ceil(11.6)的結果爲11,Math.ceil(-11.6)的結果是-12;最難掌握的是round方法,它表示「四捨五入」,算法爲Math.floor(x+0.5)。即將原來的數字加上0.5後再向下取整,因此,Math.round(11.5)的結果爲12,Math.round(-11.5)的結果爲-11。
16、如下的代碼有什麼不妥之處?
1. if(username.equals(「zxx」){}
2. int x = 1;
return x==1?true:false;
17、請說出做用域public。private,protected。以及不寫時的差異
這四個做用域的可見範圍例如如下表所看到的。
說明:假設在修飾的元素上面沒有寫不論什麼訪問修飾符。則表示friendly。
做用域 當前類同一package子孫類其它package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
備註:僅僅要記住了有4種訪問權限。4個訪問範圍,而後將全選和範圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列。就很是easy畫出上面的圖了。
18、Overload和Override的差異。Overloaded的方法可否夠改變返回值的類型?
Overload是重載的意思,Override是覆蓋的意思,也就是重寫。
重載Overload表示同一個類中可以有多個名稱一樣的方法,但這些方法的參數列表各不一樣樣(即參數個數或類型不一樣)。
重寫Override表示子類中的方法可以與父類中的某個方法的名稱和參數全然一樣,經過子類建立的實例對象調用這種方法時,將調用子類中的定義方法,這至關於把父類中定義的那個全然一樣的方法給覆蓋了,這也是面向對象編程的多態性的一種表現。子類覆蓋父類的方法時,僅僅能比父類拋出更少的異常,或者是拋出父類拋出的異常的子異常,因爲子類可以解決父類的一些問題,不能比父類有不少其它的問題。
子類方法的訪問權限僅僅能比父類的更大。不能更小。假設父類的方法是private類型。那麼,子類則不存在覆蓋的限制,至關於子類中添加了一個全新的方法。
至於Overloaded的方法可否夠改變返回值的類型這個問題。要看你倒底想問什麼呢?這個題目很是模糊。假設幾個Overloaded的方法的參數列表不同,它們的返回者類型固然也可以不同。
但我預計你想問的問題是:假設兩個方法的參數列表全然同樣,可否夠讓它們的返回值不一樣來實現重載Overload。這是不行的,咱們可以用反證法來講明這個問題。因爲咱們有時候調用一個方法時也可以不定義返回結果變量,即不要關心其返回結果,好比,咱們調用map.remove(key)方法時。儘管remove方法有返回值。但是咱們一般都不會定義接收返回結果的變量,這時候假設該類中有兩個名稱和參數列表全然一樣的方法。不過返回類型不一樣。java就沒法肯定編程者倒底是想調用哪一個方法了,因爲它沒法經過返回結果類型來推斷。
override可以翻譯爲覆蓋。從字面就可以知道,它是覆蓋了一個方法並且對其重寫。以求達到不一樣的做用。
對咱們來講最熟悉的覆蓋就是對接口方法的實現,在接口中通常僅僅是對方法進行了聲明。而咱們在實現時,就需要實現接口聲明的所有方法。
除了這個典型的使用方法之外,咱們在繼承中也可能會在子類覆蓋父類中的方法。在覆蓋要注意下面的幾點:
1、覆蓋的方法的標誌必須要和被覆蓋的方法的標誌全然匹配,才幹達到覆蓋的效果。
2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;
4、被覆蓋的方法不能爲private。不然在其子類中僅僅是新定義了一個方法。並無對其進行覆蓋。
overload對咱們來講可能比較熟悉,可以翻譯爲重載,它是指咱們可以定義一些名稱一樣的方法,經過定義不一樣的輸入參數來區分這些方法,而後再調用時。VM就會依據不一樣的參數樣式。來選擇合適的方法運行。在使用重載要注意下面的幾點:
1、在使用重載時僅僅能經過不一樣的參數樣式。好比,不一樣的參數類型,不一樣的參數個數。不一樣的參數順序(固然,同一方法內的幾個參數類型必須不同,好比可以是fun(int,float)。但是不能爲fun(int,int))。
2、不能經過訪問權限、返回類型、拋出的異常進行重載。
3、方法的異常類型和數目不會對重載形成影響;
4、對於繼承來講,假設某一方法在父類中是訪問權限是priavte,那麼就不能在子類對其進行重載,假設定義的話。也僅僅是定義了一個新方法,而不會達到重載的效果。
19、構造器Constructor是否可被override?
構造器Constructor不能被繼承。所以不能重寫Override,但可以被重載Overload。
20、接口是否可繼承接口?抽象類是否可實現(implements)接口?抽象類是否可繼承詳細類(concrete class)?
抽象類中可否夠有靜態的main方法?
接口可以繼承接口。抽象類可以實現(implements)接口。抽象類是否可繼承詳細類。
抽象類中可以有靜態的main方法。
備註:僅僅要明確了接口和抽象類的本質和做用,這些問題都很是好回答,你想一想。假設你是java語言的設計者,你是否會提供這種支持。假設不提供的話,有什麼理由嗎?假設你沒有道理不提供,那答案就是確定的了。
僅僅有記住抽象類與普通類的惟一差異就是不能建立實例對象和贊成有abstract方法。
21、寫clone()方法時。一般都有一行代碼。是什麼?
clone 有缺省行爲,super.clone();因爲首先要把父類中的成員拷貝到位,而後纔是複製本身的成員。
22、面向對象的特徵有哪些方面
計算機軟件系統是現實生活中的業務在計算機中的映射,而現實生活中的業務事實上就是一個個對象協做的過程。面向對象編程就是按現實業務同樣的方式將程序代碼按一個個對象進行組織和編寫,讓計算機系統能夠識別和理解用對象方式組織和編寫的程序代碼。這樣就行把現實生活中的業務對象映射到計算機系統中。
面向對象的編程語言有,嗎等4個基本的特徵。
1封裝:
封裝是保證軟件部件具備優良的模塊性的基礎,封裝的目標就是要實現軟件部件的「高內聚、低耦合」,防止程序相互依賴性而帶來的變更影響。
在面向對象的編程語言中。對象是封裝的最基本單位,面向對象的封裝比傳統語言的封裝更爲清晰、更爲有力。面向對象的封裝就是把描寫敘述一個對象的屬性和行爲的代碼封裝在一個「模塊」中。也就是一個類中,屬性用變量定義,行爲用方法進行定義。方法可以直接訪問同一個對象中的屬性。
一般狀況下,僅僅要記住讓變量和訪問這個變量的方法放在一塊兒。將一個類中的成員變量全部定義成私有的,僅僅有這個類本身的方法才幹夠訪問到這些成員變量。這就基本上實現對象的封裝,就很是easy找出要分配到這個類上的方法了。就基本上算是會面向對象的編程了。把握一個原則:把對同一事物進行操做的方法和相關的方法放在同一個類中。把方法和它操做的數據放在同一個類中。
好比,人要在黑板上畫圓,這一共涉及三個對象:人、黑板、圓,畫圓的方法要分配給哪一個對象呢?因爲畫圓需要使用到圓心和半徑,圓心和半徑顯然是圓的屬性,假設將它們在類中定義成了私有的成員變量,那麼,畫圓的方法必須分配給圓,它才幹訪問到圓心和半徑這兩個屬性,人之後僅僅是調用圓的畫圓方法、表示給圓發給消息而已,畫圓這種方法不該該分配在人這個對象上。這就是面向對象的封裝性。即將對象封裝成一個高度自治和相對封閉的個體,對象狀態(屬性)由這個對象本身的行爲(方法)來讀取和改變。一個更便於理解的樣例就是。司機將火車剎住了。剎車的動做是分配給司機。仍是分配給火車,顯然,應該分配給火車,因爲司機自身是不可能有那麼大的力氣將一個火車給停下來的,僅僅有火車本身才幹完畢這一動做,火車需要調用內部的離合器和剎車片等多個器件協做才幹完畢剎車這個動做,司機剎車的過程僅僅是給火車發了一個消息,通知火車要運行剎車動做而已。
抽象:
抽象就是找出一些事物的類似和共性之處,而後將這些事物歸爲一個類。這個類僅僅考慮這些事物的類似和共性之處。並且會忽略與當前主題和目標無關的那些方面,將注意力集中在與當前目標有關的方面。好比,看到一僅僅螞蟻和大象,你能夠想象出它們的一樣之處,那就是抽象。抽象包含行爲抽象和狀態抽象兩個方面。
好比。定義一個Person類,例如如下:
classPerson{
String name;
int age;
}
人原本是很是複雜的事物,有很是多方面。但因爲當前系統僅僅需要了解人的姓名和年齡,因此上面定義的類中僅僅包括姓名和年齡這兩個屬性,這就是一種抽像。使用抽象可以避免考慮一些與目標無關的細節。我對抽象的理解就是不要用顯微鏡去看一個事物的所有方面,這樣涉及的內容就太多了,而是要善於劃分問題的邊界。當前系統需要什麼,就僅僅考慮什麼。
繼承:
在定義和實現一個類的時候,可以在一個已經存在的類的基礎之上來進行,把這個已經存在的類所定義的內容做爲本身的內容,並可以增長若干新的內容,或改動原來的方法使之更適合特殊的需要,這就是繼承。繼承是子類本身主動共享父類數據和方法的機制,這是類之間的一種關係。提升了軟件的可重用性和可擴展性。
多態:
多態是指程序中定義的引用變量所指向的詳細類型和經過該引用變量發出的方法調用在編程時並不肯定,而是在程序執行期間才肯定,即一個引用變量倒底會指向哪一個類的實例對象,該引用變量發出的方法調用到底是哪一個類中實現的方法,必須在由程序執行期間才幹決定。因爲在程序執行時才肯定詳細的類。這樣,不用改動源程序代碼,就可以讓引用變量綁定到各類不一樣的類實現上。從而致使該引用調用的詳細方法隨之改變,即不改動程序代碼就可以改變程序執行時所綁定的詳細代碼。讓程序可以選擇多個執行狀態。這就是多態性。多態性加強了軟件的靈活性和擴展性。好比。如下代碼中的UserDao是一個接口。它定義引用變量userDao指向的實例對象由daofactory.getDao()在執行的時候返回,有時候指向的是UserJdbcDao這個實現,有時候指向的是UserHibernateDao這個實現,這樣,不用改動源碼,就可以改變userDao指向的詳細類實現。從而致使userDao.insertUser()方法調用的詳細代碼也隨之改變,即有時候調用的是UserJdbcDao的insertUser方法,有時候調用的是UserHibernateDao的insertUser方法:
UserDao userDao =daofactory.getDao();
userDao.insertUser(user);
比喻:人吃飯,你看到的是左手。仍是右手?
23、java中實現多態的機制是什麼?
靠的是父類或接口定義的引用變量可以指向子類或詳細實現類的實例對象。而程序調用的方法在執行期才動態綁定,就是引用變量所指向的詳細實例對象的方法,也就是內存里正在執行的那個對象的方法,而不是引用變量的類型中定義的方法。
24、abstract class和interface有什麼差異?
含有abstract修飾符的class即爲抽象類,abstract類不能建立的實例對象。
含有abstract方法的類必須定義爲abstract class。abstract class類中的方法沒必要是抽象的。
abstract class類中定義抽象方法必須在詳細(Concrete)子類中實現,因此,不能有抽象構造方法或抽象靜態方法。假設的子類沒有實現抽象父類中的所有抽象方法。那麼子類也必須定義爲abstract類型。
接口(interface)可以說成是抽象類的一種特例。接口中的所有方法都必須是抽象的。接口中的方法定義默以爲public abstract類型,接口中的成員變量類型默以爲public static final。
如下比較一下二者的語法差異:
1.抽象類可以有構造方法,接口中不能有構造方法。
2.抽象類中可以有普通成員變量,接口中沒有普通成員變量
3.抽象類中可以包括非抽象的普通方法,接口中的所有方法必須都是抽象的,不能有非抽象的普通方法。
4. 抽象類中的抽象方法的訪問類型可以是public。protected和(默認類型,儘管
eclipse下不報錯,但應該也不行)。但接口中的抽象方法僅僅能是public類型的。並且默認即爲public abstract類型。
5. 抽象類中可以包括靜態方法。接口中不能包括靜態方法
6. 抽象類和接口中都可以包括靜態成員變量。抽象類中的靜態成員變量的訪問類型可以隨意,但接口中定義的變量僅僅能是public static final類型。並且默認即爲public static final類型。
7. 一個類可以實現多個接口,但僅僅能繼承一個抽象類。
如下接着再說說二者在應用上的差異:
接口不少其它的是在系統架構設計方法發揮做用,主要用於定義模塊之間的通訊契約。而抽象類在代碼實現方面發揮做用,可以實現代碼的重用,好比。模板方法設計模式是抽象類的一個典型應用,若是某個項目的所有Servlet類都要用一樣的方式進行權限推斷、記錄訪問日誌和處理異常,那麼就可以定義一個抽象的基類,讓所有的Servlet都繼承這個抽象基類,在抽象基類的service方法中完畢權限推斷、記錄訪問日誌和處理異常的代碼。在各個子類中僅僅是完畢各自的業務邏輯代碼。僞代碼例如如下:
public abstract classBaseServlet extends HttpServlet{
public final void service(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException {
記錄訪問日誌
進行權限推斷
if(具備權限){
try{
doService(request,response);
}
catch(Excetpion e) {
記錄異常信息
}
}
}
protected abstract void doService(HttpServletRequest request,HttpServletResponse response) throws IOExcetion,ServletException;
//注意訪問權限定義成protected,顯得既專業,又嚴謹。因爲它是專門給子類用的
}
public class MyServlet1 extendsBaseServlet
{
protected voiddoService(HttpServletRequest request, HttpServletResponse response) throwsIOExcetion,ServletException
{
本Servlet僅僅處理的詳細業務邏輯代碼
}
}
父類方法中間的某段代碼不肯定。留給子類幹,就用模板方法設計模式。
備註:這道題的思路是先從總體解釋抽象類和接口的基本概念,而後再比較二者的語法細節,最後再說二者的應用差異。比較二者語法細節差異的條理是:先從一個類中的構造方法、普通成員變量和方法(包含抽象方法),靜態變量和方法,繼承性等6個方面逐一去比較回答。接着從第三者繼承的角度的回答,特別是最後用了一個典型的樣例來展示本身深厚的技術功底。
25、abstract的method是否可同一時候是static,是否可同一時候是native,是否可同一時候是synchronized?
abstract的method不可以是static的,因爲抽象的方法是要被子類實現的。而static與子類扯不上關係。
native方法表示該方法要用第二種依賴平臺的編程語言實現的。不存在着被子類實現的問題。因此。它也不能是抽象的,不能與abstract混用。好比。FileOutputSteam類要硬件打交道。底層的實現用的是操做系統相關的api實現,好比,在windows用c語言實現的。因此,查看jdk的源碼,可以發現FileOutputStream的open方法的定義例如如下:
private native void open(Stringname) throws FileNotFoundException;
假設咱們要用java調用別人寫的c語言函數。咱們是沒法直接調用的,咱們需要依照java的要求寫一個c語言的函數,又咱們的這個c語言函數去調用別人的c語言函數。由於咱們的c語言函數是按java的要求來寫的,咱們這個c語言函數就可以與java對接上。java那邊的對接方式就是定義出與咱們這個c函數相相應的方法。java中相應的方法不需要寫詳細的代碼。但需要在前面聲明native。
關於synchronized與abstract合用的問題。我認爲也不行,因爲在我幾年的學習和開發中,歷來沒見到過這樣的狀況,而且我認爲synchronized應該是做用在一個詳細的方法上纔有意義。
而且,方法上的synchronized同步所使用的同步鎖對象是this,而抽象方法上沒法肯定this是什麼。
26、什麼是內部類?Static Nested Class和Inner Class的不一樣。
內部類就是在一個類的內部定義的類。內部類中不能定義靜態成員(靜態成員不是對象的特性,僅僅是爲了找一個容身之處,因此需要放到一個類中而已。這麼一點小事。你還要把它放到類內部的一個類中,過度了啊!提供內部類。不是爲讓你幹這樣的事情,無聊,不讓你幹。我想多是既然靜態成員相似c語言的全局變量,而內部類通常是用於建立內部對象用的,因此,把「全局變量」放在內部類中就是毫無心義的事情,既然是毫無心義的事情,就應該被禁止),內部類可以直接訪問外部類中的成員變量,內部類可以定義在外部類的方法外面,也可以定義在外部類的方法體中,例如如下所看到的:
public class Outer
{
int out_x = 0;
public void method()
{
Inner1 inner1 = new Inner1();
public class Inner2 //在方法體內部定義的內部類
{
public method()
{
out_x = 3;
}
}
Inner2 inner2 = new Inner2();
}
public class Inner1 //在方法體外面定義的內部類
{
}
}
在方法體外面定義的內部類的訪問類型可以是public,protecte,默認的。private等4種類型。這就好像類中定義的成員變量有4種訪問類型同樣,它們決定這個內部類的定義對其它類是否可見。對於這樣的狀況,咱們也可以在外面建立內部類的實例對象。建立內部類的實例對象時,必定要先建立外部類的實例對象,而後用這個外部類的實例對象去建立內部類的實例對象,代碼例如如下:
Outer outer = new Outer();
Outer.Inner1 inner1 = outer.newInnner1();
在方法內部定義的內部類前面不能有訪問類型修飾符,就好像方法中定義的局部變量同樣,但這樣的內部類的前面可以使用final或abstract修飾符。這樣的內部類對其它類是不可見的其它類沒法引用這樣的內部類,但是這樣的內部類建立的實例對象可以傳遞給其它類訪問。這樣的內部類必須是先定義,後使用,即內部類的定義代碼必須出現在使用該類以前。這與方法中的局部變量必須先定義後使用的道理也是同樣的。這樣的內部類可以訪問方法體中的局部變量。但是。該局部變量前必須加final修飾符。
對於這些細節。僅僅要在eclipse寫代碼試試。依據開發工具提示的各種錯誤信息就可以當即瞭解到。
在方法體內部還可以採用例如如下語法來建立一種匿名內部類。即定義某一接口或類的子類的同一時候。還建立了該子類的實例對象。無需爲該子類定義名稱:
public class Outer
{
public void start()
{
new Thread(
new Runable(){
public void run(){};
}
).start();
}
}
最後。在方法外部定義的內部類前面可以加上statickeyword,從而成爲Static Nested Class,它再也不具備內部類的特性,所有。從狹義上講,它不是內部類。Static Nested Class與普通類在執行時的行爲和功能上沒有什麼區別,僅僅是在編程引用時的語法上有一些區別。它可以定義成public、protected、默認的、private等多種類型。而普通類僅僅能定義成public和默認的這兩種類型。在外面引用Static Nested Class類的名稱爲「外部類名.內部類名」。
在外面不需要建立外部類的實例對象。就可以直接建立Static Nested Class,好比,若是Inner是定義在Outer類中的Static Nested Class。那麼可以使用例如如下語句建立Inner類:
Outer.Inner inner = newOuter.Inner();
由於static Nested Class不依賴於外部類的實例對象。因此,static Nested Class能訪問外部類的非static成員變量。
當在外部類中訪問Static Nested Class時。可以直接使用Static Nested Class的名字。而不需要加上外部類的名字了,在Static Nested Class中也可以直接引用外部類的static的成員變量,不需要加上外部類的名字。
在靜態方法中定義的內部類也是Static Nested Class,這時候不能在類前面加statickeyword。靜態方法中的Static Nested Class與普通方法中的內部類的應用方式很是類似。它除了可以直接訪問外部類中的static的成員變量,還可以訪問靜態方法中的局部變量,但是,該局部變量前必須加final修飾符。
備註:首先依據你的印象說出你對內部類的總體方面的特色:好比。在兩個地方可以定義,可以訪問外部類的成員變量。不能定義靜態成員。這是大的特色。而後再說一些細節方面的知識。好比。幾種定義方式的語法差異,靜態內部類。以及匿名內部類。
27、內部類可以引用它的包括類的成員嗎?有沒有什麼限制?
全然可以。假設不是靜態內部類,那沒有什麼限制!
假設你把靜態嵌套類看成內部類的一種特例,那在這樣的狀況下不可以訪問外部類的普通成員變量,而僅僅能訪問外部類中的靜態成員。好比,如下的代碼:
class Outer
{
static int x;
static class Inner
{
void test()
{
syso(x);
}
}
}
答題時,也要能察言觀色。揣摩提問者的心思,顯然人家但願你說的是靜態內部類不能訪問外部類的成員,但你一上來就頂牛,這很差。要先順着人家。讓人家愜意。而後再說特殊狀況,讓人家驚訝。
28、Anonymous Inner Class (匿名內部類)可否夠extends(繼承)其餘類。可否夠implements(實現)interface(接口)?
可以繼承其它類或實現其它接口。
不只是可以,而是必須!
29、super.getClass()方法調用
如下程序的輸出結果是多少?
importjava.util.Date;
public classTestextends Date{
public static voidmain(String[] args) {
new Test().test();
}
public void test(){
System.out.println(super.getClass().getName());
}
}
很是奇怪。結果是Test
這屬於腦筋急轉彎的題目,在一個qq羣有個網友正好問過這個問題,我認爲挺有趣。就研究了一下,沒想到今天還被你面到了。哈哈。
在test方法中。直接調用getClass().getName()方法。返回的是Test類名
由於getClass()在Object類中定義成了final,子類不能覆蓋該方法,因此。在
test方法中調用getClass().getName()方法,事實上就是在調用從父類繼承的getClass()方法。等效於調用super.getClass().getName()方法,因此。super.getClass().getName()方法返回的也應該是Test。
假設想獲得父類的名稱。應該用例如如下代碼:
getClass().getSuperClass().getName();
30、String是最主要的數據類型嗎?
基本數據類型包含byte、int、char、long、float、double、boolean和short。
java.lang.String類是final類型的,所以不可以繼承這個類、不能改動這個類。
爲了提升效率節省空間,咱們應該用StringBuffer類
31、String s = "Hello";s = s + " world!";這兩行代碼運行後,原始的String對象中的內容究竟變了沒有?
沒有。
因爲String被設計成不可變(immutable)類。因此它的所有對象都是不可變對象。在這段代碼中,s原先指向一個String對象。內容是 "Hello",而後咱們對s進行了+操做,那麼s所指向的那個對象是否發生了改變呢?答案是沒有。
這時,s不指向原來那個對象了。而指向了還有一個 String對象,內容爲"Hello world!"。原來那個對象還存在於內存之中。僅僅是s這個引用變量再也不指向它了。
經過上面的說明,咱們很是easy導出還有一個結論。假設經常對字符串進行各類各樣的改動,或者說,不可預見的改動。那麼使用String來表明字符串的話會引發很是大的內存開銷。因爲 String對象創建以後不能再改變,因此對於每一個不一樣的字符串。都需要一個String對象來表示。
這時,應該考慮使用StringBuffer類,它贊成改動。而不是每一個不一樣的字符串都要生成一個新的對象。並且,這兩種類的對象轉換十分easy。
同一時候,咱們還可以知道,假設要使用內容一樣的字符串。沒必要每次都new一個String。好比咱們要在構造器中對一個名叫s的String引用變量進行初始化,把它設置爲初始值,應當這樣作:
public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}
而非
s = new String("Initial Value");
後者每次都會調用構造器,生成新對象,性能低下且內存開銷大,並且沒有意義。因爲String對象不可改變,因此對於內容一樣的字符串,僅僅要一個String對象來表示就可以了。也就說,屢次調用上面的構造器建立多個對象,他們的String類型屬性s都指向同一個對象。
上面的結論還基於這樣一個事實:對於字符串常量,假設內容一樣,Java以爲它們表明同一個String對象。而用keywordnew調用構造器,老是會建立一個新的對象,無論內容是否一樣。
至於爲何要把String類設計成不可變類,是它的用途決定的。事實上不只僅String,很是多Java標準類庫中的類都是不可變的。在開發一個系統的時候,咱們有時候也需要設計不可變類。來傳遞一組相關的值。這也是面向對象思想的體現。不可變類有一些長處,比方因爲它的對象是僅僅讀的,因此多線程併發訪問也不會有不論什麼問題。
固然也有一些缺點,比方每個不一樣的狀態都要一個對象來表明。可能會形成性能上的問題。因此Java標準類庫還提供了一個可變版本號,即 StringBuffer。
32、可否夠繼承String類?
String類是final類故不可以繼承。
33、String s = new String("xyz");建立了幾個String Object?兩者之間有什麼差異?
兩個或一個,」xyz」相應一個對象,這個對象放在字符串常量緩衝區,常量」xyz」不管出現多少遍,都是緩衝區中的那一個。New String每寫一遍,就建立一個新的對象,它一句那個常量」xyz」對象的內容來建立出一個新String對象。假設曾經就用過’xyz’,這句表明就不會建立」xyz」本身了,直接從緩衝區拿。
34、String和StringBuffer的差異
JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操做字符串。即包括多個字符的字符數據。這個String類提供了數值不可改變的字符串。而這個StringBuffer類提供的字符串進行改動。
當你知道字符數據要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字符數據。
另外,String實現了equals方法,new String(「abc」).equals(newString(「abc」)的結果爲true,而StringBuffer沒有實現equals方法,因此,new StringBuffer(「abc」).equals(newStringBuffer(「abc」)的結果爲false。
接着要舉一個詳細的樣例來講明,咱們要把1到100的所有數字拼起來,組成一個串。
StringBuffer sbf = new StringBuffer();
for(int i=0;i<100;i++)
{
sbf.append(i);
}
上面的代碼效率很是高,因爲僅僅建立了一個StringBuffer對象,而如下的代碼效率很是低,因爲建立了101個對象。
String str = new String();
for(int i=0;i<100;i++)
{
str = str + i;
}
在講二者差異時,應把循環的次數搞成10000,而後用endTime-beginTime來比較二者運行的時間差別。最後還要講講StringBuilder與StringBuffer的差異。
String覆蓋了equals方法和hashCode方法,而StringBuffer沒有覆蓋equals方法和hashCode方法,因此,將StringBuffer對象存儲進Java集合類中時會出現故障。
35、怎樣把一段逗號切割的字符串轉換成一個數組?
假設不查jdk api,我很是難寫出來!
我可以說說個人思路:
1 用正則表達式,代碼大概爲:String [] result = orgStr.split(「,」);
2 用 StingTokenizer ,代碼爲:StringTokenizer tokener = StringTokenizer(orgStr,」,」);
String [] result =new String[tokener .countTokens()];
Int i=0;
while(tokener.hasNext(){result[i++]=toker.nextToken();}
36、數組有沒有length()這種方法?
String有沒有length()這種方法?
數組沒有length()這種方法,有length的屬性。String有有length()這種方法。
37、如下這條語句一共建立了多少個對象:String s="a"+"b"+"c"+"d";
答:對於例如如下代碼:
String s2 = s1 + "b";
String s3 = "a" + "b";
System.out.println(s2 == "ab");
System.out.println(s3 == "ab");
第一條語句打印的結果爲false。第二條語句打印的結果爲true。這說明javac編譯可以對字符串常量直接相加的表達式進行優化,沒必要要等到執行期去進行加法運算處理,而是在編譯時去掉當中的加號,直接將其編譯成一個這些常量相連的結果。
題目中的第一行代碼被編譯器在編譯時優化後,至關於直接定義了一個」abcd」的字符串,因此。上面的代碼應該僅僅建立了一個String對象。
寫例如如下兩行代碼。
String s ="a" + "b" + "c" + "d";
System.out.println(s== "abcd");
終於打印的結果應該爲true。
38、try {}裏有一個return語句,那麼緊跟在這個try後的finally {}裏的code會不會被運行。何時被運行,在return前仍是後?
或許你的答案是在return以前,但往更細地說,個人答案是在return中間執行,請看如下程序代碼的執行結果:
public classTest {
/**
* @paramargs add by zxx ,Dec 9, 2008
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
System.out.println(newTest().test());;
}
static int test()
{
int x = 1;
try
{
returnx;
}
finally
{
++x;
}
}
}
---------運行結果 ---------
1
執行結果是1,爲何呢?主函數調用子函數並獲得結果的過程,比如主函數準備一個空罐子,當子函數要返回結果時,先把結果放在罐子裏。而後再將程序邏輯返回到主函數。所謂返回,就是子函數說,我不執行了,你主函數繼續執行吧。這沒什麼結果可言,結果是在說這話以前放進罐子裏的。
39、如下的程序代碼輸出的結果是多少?
public class smallT
{
public staticvoid main(String args[])
{
smallT t = new smallT();
int b = t.get();
System.out.println(b);
}
public int get()
{
try
{
return1 ;
}
finally
{
return2 ;
}
}
}
返回的結果是2。
我可以經過如下一個樣例程序來幫助我解釋這個答案。從如下樣例的運行結果中可以發現,try中的return語句調用的函數先於finally中調用的函數運行,也就是說return語句先運行,finally語句後運行,因此,返回的結果是2。Return並不是讓函數當即返回。而是return語句運行後,將把返回結果放置進函數棧中,此時函數並不是當即返回,它要運行finally語句後才真正開始返回。
在解說答案時可以用如下的程序來幫助分析:
public classTest {
/**
* @paramargs add by zxx ,Dec 9, 2008
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
System.out.println(newTest().test());;
}
int test()
{
try
{
return func1();
}
finally
{
return func2();
}
}
int func1()
{
System.out.println("func1");
return 1;
}
int func2()
{
System.out.println("func2");
return 2;
}
}
-----------運行結果-----------------
func1
func2
2
結論:finally中的代碼比return和break語句後運行
40、final, finally, finalize的差異。
final 用於聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
內部類要訪問局部變量,局部變量必須定義成final類型,好比,一段代碼……
finally是異常處理語句結構的一部分。表示老是運行。
finalize是Object類的一個方法,在垃圾收集器運行的時候會調用被回收對象的此方法。可以覆蓋此方法提供垃圾收集時的其它資源回收,好比關閉文件等。
JVM不保證此方法總被調用
41、執行時異常與通常異常有何異同?
異常表示程序執行過程當中可能出現的非正常狀態。執行時異常表示虛擬機的一般操做中可能遇到的異常,是一種常見執行錯誤。java編譯器要求方法必須聲明拋出可能發生的非執行時異常,但是並不要求必須聲明拋出未被捕獲的執行時異常。
42、error和exception有什麼差異?
error 表示恢復不是不可能但很是困難的狀況下的一種嚴重問題。比方說內存溢出。不可能期望程序能處理這種狀況。
exception表示一種設計或實現問題。也就是說。它表示假設程序執行正常,從不會發生的狀況。
43、Java中的異常處理機制的簡單原理和應用。
異常是指java程序執行時(非編譯)所發生的非正常狀況或錯誤,與現實生活中的事件很是類似,現實生活中的事件可以包括事件發生的時間、地點、人物、情節等信息。可以用一個對象來表示,Java使用面向對象的方式來處理異常,它把程序中發生的每個異常也都分別封裝到一個對象來表示的。該對象中包括有異常的信息。
Java對異常進行了分類,不一樣類型的異常分別用不一樣的Java類表示,所有異常的根類爲java.lang.Throwable,Throwable如下又派生了兩個子類:Error和Exception,Error表示應用程序自己沒法克服和恢復的一種嚴重問題,程序僅僅有死的份了,好比,說內存溢出和線程死鎖等系統問題。Exception表示程序還能夠克服和恢復的問題。當中又分爲系統異常和普通異常。系統異常是軟件自己缺陷所致使的問題。也就是軟件開發者考慮不周所致使的問題,軟件使用者沒法克服和恢復這樣的問題,但在這樣的問題下還可讓軟件系統繼續執行或者讓軟件死掉。好比,數組腳本越界(ArrayIndexOutOfBoundsException),空指針異常(NullPointerException)、類轉換異常(ClassCastException)。普通異常是執行環境的變化或異常所致使的問題。是用戶能夠克服的問題,好比,網絡斷線。硬盤空間不夠,發生這樣的異常後,程序不該該死掉。
java爲系統異常和普通異常提供了不一樣的解決方式,編譯器強制普通異常必須try..catch處理或用throws聲明繼續拋給上層調用方法處理,因此普通異常也稱爲checked異常,而系統異常可以處理也可以不處理。因此。編譯器不強制用try..catch處理或用throws聲明。因此係統異常也稱爲unchecked異常。
提示答題者:就依照三個級別去思考:虛擬機必須宕機的錯誤。程序可以死掉也可以不死掉的錯誤,程序不該該死掉的錯誤;
44、請寫出你最多見到的5個runtime exception。
這道題主要考你的代碼量究竟多大,假設你長期寫代碼的,應該經常都看到過一些系統方面的異常,你不必定真要回答出5個詳細的系統異常。但你要能夠說出什麼是系統異常。以及幾個系統異常就好了,固然,這些異常全然用其英文名稱來寫是最好的,假設實在寫不出,那就用中文吧,有總比沒有強!
所謂系統異常,就是…..。它們都是RuntimeException的子類。在jdk doc中查RuntimeException類,就可以看到其所有的子類列表,也就是看到了所有的系統異常。我比較有印象的系統異常有:NullPointerException、ArrayIndexOutOfBoundsException、ClassCastException。
45、JAVA語言怎樣進行異常處理,keyword:throws,throw,try,catch,finally分別表明什麼意義?在try塊中可以拋出異常嗎?
46、java中有幾種方法可以實現一個線程?用什麼keyword修飾同步方法?
stop()和suspend()方法爲什麼不推薦使用?
java5曾經,有例如如下兩種:
第一種:
new Thread(){}.start();這表示調用Thread子類對象的run方法。new Thread(){}表示一個Thread的匿名子類的實例對象,子類加上run方法後的代碼例如如下:
new Thread(){
public void run(){
}
}.start();
另一種:
new Thread(new Runnable(){}).start();這表示調用Thread對象接受的Runnable對象的run方法,new Runnable(){}表示一個Runnable的匿名子類的實例對象,runnable的子類加上run方法後的代碼例如如下:
new Thread(new Runnable(){
public voidrun(){
}
}
).start();
從java5開始,還有例如如下一些線程池建立多線程的方式:
ExecutorService pool = Executors.newFixedThreadPool(3)
for(int i=0;i<10;i++)
{
pool.execute(newRunable(){public void run(){}});
}
Executors.newCachedThreadPool().execute(new Runable(){publicvoid run(){}});
Executors.newSingleThreadExecutor().execute(new Runable(){publicvoid run(){}});
有兩種實現方法。分別使用new Thread()和new Thread(runnable)形式。第一種直接調用thread的run方法,因此,咱們每每使用Thread子類,即new SubThread()。
另一種調用runnable的run方法。
有兩種實現方法,各自是繼承Thread類與實現Runnable接口
用synchronizedkeyword修飾同步方法
反對使用stop(),是因爲它不安全。
它會解除由線程獲取的所有鎖定。而且假設對象處於一種不連貫狀態,那麼其它線程能在那種狀態下檢查和改動它們。
結果很是難檢查出真正的問題所在。suspend()方法easy發生死鎖。調用suspend()的時候,目標線程會停下來。但卻仍然持有在這以前得到的鎖定。此時。其它不論什麼線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復執行。對不論什麼線程來講,假設它們想恢復目標線程,同一時候又試圖使用不論什麼一個鎖定的資源,就會形成死鎖。因此不該該使用suspend(),而應在本身的Thread類中置入一個標誌,指出線程應該活動仍是掛起。
若標誌指出線程應該掛起,便用wait()命其進入等待狀態。
若標誌指出線程應當恢復,則用一個notify()又一次啓動線程。
47、sleep()和 wait()有什麼差異?
(網上的答案:sleep是線程類(Thread)的方法,致使此線程暫停運行指定時間。給運行機會給其它線程,但是監控狀態依舊保持,到時後會本身主動恢復。調用sleep不會釋放對象鎖。 wait是Object類的方法,對此對象調用wait方法致使本線程放棄對象鎖,進入等待此對象的等待鎖定池。僅僅有針對此對象發出notify方法(或notifyAll)後本線程才進入對象鎖定池準備得到對象鎖進入運行狀態。)
sleep就是正在運行的線程主動讓出cpu。cpu去運行其它線程。在sleep指定的時間事後,cpu纔會回到這個線程上繼續往下運行,假設當前線程進入了同步鎖,sleep方法並不會釋放鎖,即便當前線程使用sleep方法讓出了cpu。但其它被同步鎖擋住了的線程也沒法獲得運行。
wait是指在一個已經進入了同步鎖的線程內,讓本身臨時讓出同步鎖,以便其它正在等待此鎖的線程可以獲得同步鎖並運行,僅僅有其它線程調用了notify方法(notify並不釋放鎖,僅僅是告訴調用過wait方法的線程可以去參與得到鎖的競爭了。但不是當即獲得鎖,因爲鎖還在別人手裏,別人還沒釋放。假設notify方法後面的代碼還有很是多,需要這些代碼運行完後纔會釋放鎖。可以在notfiy方法後添加一個等待和一些代碼,看看效果),調用wait方法的線程就會解除wait狀態和程序可以再次獲得鎖後繼續向下運行。
對於wait的解說必定要配合樣例代碼來講明,才顯得本身真明確。
package com.huawei.interview;
publicclass MultiThread {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
new Thread(newThread1()).start();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catchblock
e.printStackTrace();
}
new Thread(newThread2()).start();
}
private static classThread1implements Runnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
//因爲這裏的Thread1和如下的Thread2內部run方法要用同一對象做爲監視器,咱們這裏不能用this,因爲在Thread2裏面的this和這個Thread1的this不是同一個對象。咱們用MultiThread.class這個字節碼對象,當前虛擬機裏引用這個變量時,指向的都是同一個對象。
synchronized (MultiThread.class){
System.out.println("enterthread1...");
System.out.println("thread1is waiting");
try {
//釋放鎖有兩種方式。第一種方式是程序天然離開監視器的範圍,也就是離開了synchronizedkeyword管轄的代碼範圍。還有一種方式就是在synchronizedkeyword管轄的代碼內部調用監視器對象的wait方法。
這裏,使用wait方法釋放鎖。
MultiThread.class.wait();
} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println("thread1is going on...");
System.out.println("thread1is being over!");
}
}
}
private static classThread2implements Runnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
synchronized (MultiThread.class){
System.out.println("enterthread2...");
System.out.println("thread2notify other thread can release wait status..");
//因爲notify方法並不釋放鎖,即便thread2調用如下的sleep方法歇息了10毫秒,但thread1仍然不會運行,因爲thread2沒有釋放鎖,因此Thread1沒法得不到鎖。
MultiThread.class.notify();
System.out.println("thread2is sleeping ten millisecond...");
try {
Thread.sleep(10);
} catch (InterruptedExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
System.out.println("thread2is going on...");
System.out.println("thread2is being over!");
}
}
}
}
48、同步和異步有何異同,在什麼狀況下分別使用他們?舉例說明。
假設數據將在線程間共享。好比正在寫的數據之後可能被還有一個線程讀到,或者正在讀的數據可能已經被還有一個線程寫過了。那麼這些數據就是共享數據。必須進行同步存取。
當應用程序在對象上調用了一個需要花費很是長時間來運行的方法,並且不但願讓程序等待方法的返回時,就應該使用異步編程。在很是多狀況下採用異步途徑每每更有效率。
49. 如下兩個方法同步嗎?(本身發明)
class Test
{
synchronizedstatic voidsayHello3()
{
}
synchronizedvoid getX(){}
}
50、多線程有幾種實現方法?同步有幾種實現方法?
多線程有兩種實現方法,各自是繼承Thread類與實現Runnable接口
同步的實現方面有兩種,各自是synchronized,wait與notify
wait():使一個線程處於等待狀態,並且釋放所持有的對象的lock。
sleep():使一個正在執行的線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
notify():喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程。而且不是按優先級。
Allnotity():喚醒所有處入等待狀態的線程。注意並不是給所有喚醒線程一個對象的鎖。而是讓它們競爭。
51、啓動一個線程是用run()仍是start()? .
啓動一個線程是調用start()方法,使線程就緒狀態,之後可以被調度爲運行狀態,一個線程必須關聯一些詳細的運行代碼,run()方法是該線程所關聯的運行代碼。
52、當一個線程進入一個對象的一個synchronized方法後,其餘線程是否可進入此對象的其餘方法?
分幾種狀況:
1.其它方法前是否加了synchronizedkeyword。假設沒加,則能。
2.假設這種方法內部調用了wait,則可以進入其它synchronized方法。
3.假設其它個方法都加了synchronizedkeyword,並且內部沒有調用wait。則不能。
4.假設其它方法是static。它用的同步鎖是當前類的字節碼,與非靜態的方法不能同步。因爲非靜態的方法用的是this。
53、線程的基本概念、線程的基本狀態以及狀態之間的關係
一個程序中可以有多條運行線索同一時候運行,一個線程就是程序中的一條運行線索。每個線程上都關聯有要運行的代碼。即可以有多段程序代碼同一時候運行,每個程序至少都有一個線程,即main方法運行的那個線程。
假設僅僅是一個cpu,它怎麼可以同一時候運行多段程序呢?這是從宏觀上來看的,cpu一會運行a線索。一會運行b線索,切換時間很是快,給人的感受是a,b在同一時候運行,比如你們在同一個辦公室上網,僅僅有一條連接到外部網線。事實上,這條網線一會爲a傳數據,一會爲b傳數據。由於切換時間很是短暫,因此,你們感受都在同一時候上網。
狀態:就緒,執行。synchronize堵塞,wait和sleep掛起,結束。
wait必須在synchronized內部調用。
調用線程的start方法後線程進入就緒狀態。線程調度系統將就緒狀態的線程轉爲執行狀態。遇到synchronized語句時。由執行狀態轉爲堵塞。當synchronized得到鎖後,由堵塞轉爲執行,在這樣的狀況可以調用wait方法轉爲掛起狀態。當線程關聯的代碼執行完後,線程變爲結束狀態。
54、簡述synchronized和java.util.concurrent.locks.Lock的異同?
主要一樣點:Lock能完畢synchronized所實現的所有功能
主要不一樣點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會本身主動釋放鎖,而Lock必定要求程序猿手工釋放,並且必須在finally從句中釋放。Lock還有更強大的功能。好比。它的tryLock方法可以非堵塞方式去拿鎖。
舉例說明(對如下的題用lock進行了改寫):
package com.huawei.interview;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
publicclass ThreadTest {
/**
* @paramargs
*/
private int j;
private Lock lock =newReentrantLock();
public static voidmain(String[] args) {
// TODO Auto-generated method stub
ThreadTest tt = new ThreadTest();
for(int i=0;i<2;i++)
{
new Thread(tt.new Adder()).start();
new Thread(tt.new Subtractor()).start();
}
}
private class SubtractorimplementsRunnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j--="+ j--);
//這裏拋異常了。鎖能釋放嗎?
}*/
lock.lock();
try
{
System.out.println("j--="+ j--);
}finally
{
lock.unlock();
}
}
}
}
private class AdderimplementsRunnable
{
@Override
public void run() {
// TODO Auto-generated methodstub
while(true)
{
/*synchronized (ThreadTest.this) {
System.out.println("j++="+ j++);
}*/
lock.lock();
try
{
System.out.println("j++="+ j++);
}finally
{
lock.unlock();
}
}
}
}
}
55、設計4個線程。當中兩個線程每次對j添加1,另外兩個線程對j每次下降1。寫出程序。
下面程序使用內部類實現線程。對j增減的時候沒有考慮順序問題。
public class ThreadTest1
{
private int j;
public static void main(String args[]){
ThreadTest1 tt=newThreadTest1();
Inc inc=tt.new Inc();
Dec dec=tt.new Dec();
for(inti=0;i<2;i++){
Thread t=newThread(inc);
t.start();
t=new Thread(dec);
t.start();
}
}
private synchronized void inc(){
j++;
System.out.println(Thread.currentThread().getName()+"-inc:"+j);
}
private synchronized void dec(){
j--;
System.out.println(Thread.currentThread().getName()+"-dec:"+j);
}
class Inc implements Runnable{
public void run(){
for(inti=0;i<100;i++){
inc();
}
}
}
class Dec implements Runnable{
public void run(){
for(inti=0;i<100;i++){
dec();
}
}
}
}
----------隨手再寫的一個-------------
class A
{
JManger j =new JManager();
main()
{
new A().call();
}
void call
{
for(int i=0;i<2;i++)
{
new Thread(
newRunnable(){ public void run(){while(true){j.accumulate()}}}
).start();
new Thread(newRunnable(){ public void run(){while(true){j.sub()}}}).start();
}
}
}
class JManager
{
private j = 0;
public synchronized voidsubtract()
{
j--
}
public synchronized voidaccumulate()
{
j++;
}
}
56、子線程循環10次,接着主線程循環100,接着又回到子線程循環10次,接着再回到主線程又循環100,如此循環50次,請寫出程序。
終於的程序代碼例如如下:
publicclass ThreadTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
new ThreadTest().init();
}
public void init()
{
final Business business =newBusiness();
new Thread(
new Runnable()
{
public voidrun() {
for(inti=0;i<50;i++)
{
business.SubThread(i);
}
}
}
).start();
for(int i=0;i<50;i++)
{
business.MainThread(i);
}
}
private class Business
{
booleanbShouldSub =true;//這裏至關於定義了控制該誰運行的一個信號燈
public synchronized voidMainThread(int i)
{
if(bShouldSub)
try {
this.wait();
} catch(InterruptedException e) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
for(int j=0;j<5;j++)
{
System.out.println(Thread.currentThread().getName()+ ":i=" + i +",j=" + j);
}
bShouldSub =true;
this.notify();
}
public synchronized voidSubThread(int i)
{
if(!bShouldSub)
try {
this.wait();
} catch (InterruptedExceptione) {
// TODO Auto-generatedcatch block
e.printStackTrace();
}
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ":i=" + i +",j=" + j);
}
bShouldSub =false;
this.notify();
}
}
}
備註:不可能一上來就寫出上面的完整代碼,最初寫出來的代碼例如如下,問題在於兩個線程的代碼要參照同一個變量,即這兩個線程的代碼要共享數據,因此,把這兩個線程的運行代碼搬到同一個類中去:
package com.huawei.interview.lym;
publicclass ThreadTest {
private static booleanbShouldMain=false;
public static void main(String[]args) {
// TODO Auto-generated method stub
/*new Thread(){
public void run()
{
for(int i=0;i<50;i++)
{
for(int j=0;j<10;j++)
{
System.out.println("i="+ i + ",j=" + j);
}
}
}
}.start();*/
//final String str = newString("");
new Thread(
new Runnable()
{
public voidrun()
{
for(inti=0;i<50;i++)
{
synchronized(ThreadTest.class) {
if(bShouldMain)
{
try {
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(intj=0;j<10;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i="+ i + ",j=" + j);
}
bShouldMain= true;
ThreadTest.class.notify();
}
}
}
}
).start();
for(int i=0;i<50;i++)
{
synchronized (ThreadTest.class){
if(!bShouldMain)
{
try {
ThreadTest.class.wait();}
catch(InterruptedException e) {
e.printStackTrace();
}
}
for(intj=0;j<5;j++)
{
System.out.println(
Thread.currentThread().getName()+
"i=" + i +",j=" + j);
}
bShouldMain =false;
ThreadTest.class.notify();
}
}
}
}
如下使用jdk5中的併發庫來實現的:
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class ThreadTest
{
private static Locklock = new ReentrantLock();
private staticCondition subThreadCondition = lock.newCondition();
private staticboolean bBhouldSubThread = false;
public static voidmain(String [] args)
{
ExecutorServicethreadPool = Executors.newFixedThreadPool(3);
threadPool.execute(newRunnable(){
publicvoid run()
{
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(!bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= false;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
});
threadPool.shutdown();
for(inti=0;i<50;i++)
{
lock.lock();
try
{
if(bBhouldSubThread)
subThreadCondition.await();
for(intj=0;j<10;j++)
{
System.out.println(Thread.currentThread().getName()+ ",j=" + j);
}
bBhouldSubThread= true;
subThreadCondition.signal();
}catch(Exceptione)
{
}
finally
{
lock.unlock();
}
}
}
}
57、介紹Collection框架的結構
答:任意發揮題,天南海北誰便談。僅僅要讓別認爲你知識淵博,理解透徹就能夠。
58、Collection框架中實現比較要實現什麼接口
comparable/comparator
59、ArrayList和Vector的差異
答:
這兩個類都實現了List接口(List接口繼承了Collection接口),他們都是有序集合,即存儲在這兩個集合中的元素的位置都是有順序的,至關於一種動態的數組,咱們之後可以按位置索引號取出某個元素。。並且當中的數據是贊成反覆的,這是HashSet之類的集合的最大不一樣處,HashSet之類的集合不可以按索引號去檢索當中的元素,也不一樣意有反覆的元素(原本題目問的與hashset沒有不論什麼關係。但爲了說清楚ArrayList與Vector的功能,咱們使用對例如式。更有利於說明問題)。
接着才說ArrayList與Vector的差異。這主要包含兩個方面:.
(1)同步性:
Vector是線程安全的。也就是說是它的方法之間是線程同步的。而ArrayList是線程序不安全的。它的方法之間是線程不一樣步的。
假設僅僅有一個線程會訪問到集合,那最好是使用ArrayList,因爲它不考慮線程安全,效率會高些;假設有多個線程會訪問到集合。那最好是使用Vector。因爲不需要咱們本身再去考慮和編寫線程安全的代碼。
備註:對於Vector&ArrayList、Hashtable&HashMap,要記住線程安全的問題,記住Vector與Hashtable是舊的,是java一誕生就提供了的。它們是線程安全的,ArrayList與HashMap是java2時才提供的,它們是線程不安全的。
因此。咱們講課時先講老的。
(2)數據增加:
ArrayList與Vector都有一個初始的容量大小,當存儲進它們裏面的元素的個數超過了容量時,就需要添加ArrayList與Vector的存儲空間。每次要添加存儲空間時,不是僅僅添加一個存儲單元,而是添加多個存儲單元,每次添加的存儲單元的個數在內存空間利用與程序效率之間要取得必定的平衡。Vector默認增加爲原來兩倍,而ArrayList的增加策略在文檔中沒有明白規定(從源碼看到的是增加爲原來的1.5倍)。
ArrayList與Vector都可以設置初始的空間大小。Vector還可以設置增加的空間大小,而ArrayList沒有提供設置增加空間的方法。
總結:即Vector增加原來的一倍,ArrayList添加原來的0.5倍。
60、HashMap和Hashtable的差異
(條理上還需要整理,也是先說一樣點,再說不一樣點)
HashMap是Hashtable的輕量級實現(非線程安全的實現)。他們都完畢了Map接口,主要差異在於HashMap贊成空(null)鍵值(key),由於非線程安全。在僅僅有一個線程訪問的狀況下,效率要高於Hashtable。
HashMap贊成將null做爲一個entry的key或者value,而Hashtable不一樣意。
HashMap把Hashtable的contains方法去掉了,改爲containsvalue和containsKey。因爲contains方法easy讓人引發誤解。
Hashtable繼承自Dictionary類。而HashMap是Java1.2引進的Map interface的一個實現。
最大的不一樣是,Hashtable的方法是Synchronize的,而HashMap不是。在多個線程訪問Hashtable時。不需要本身爲它的方法實現同步。而HashMap就必須爲之提供外同步。
Hashtable和HashMap採用的hash/rehash算法都大概同樣。因此性能不會有很是大的差別。
就HashMap與HashTable主要從三方面來講。
一.歷史緣由:Hashtable是基於陳舊的Dictionary類的,HashMap是Java 1.2引進的Map接口的一個實現
二.同步性:Hashtable是線程安全的,也就是說是同步的。而HashMap是線程序不安全的。不是同步的
三.值:僅僅有HashMap可以讓你將空值做爲一個表的條目的key或value
61、List和 Map差異?
一個是存儲單列數據的集合,還有一個是存儲鍵和值這種雙列數據的集合。List中存儲的數據是有順序,並且贊成反覆。Map中存儲的數據是沒有順序的,其鍵是不能反覆的,它的值是可以有反覆的。
62、List, Set, Map是否繼承自Collection接口?
List。Set是。Map不是
63、List、Map、Set三個接口。存取元素時,各有什麼特色?
這種題屬於任意發揮題:這種題比較考水平。兩個方面的水平:一是要真正明確這些內容,二是要有較強的總結和表述能力。
假設你明確。但表述不清楚,在別人那裏則等同於不明確。
首先。List與Set具備類似性。它們都是單列元素的集合,因此,它們有一個功共同的父接口,叫Collection。
Set裏面不一樣意有反覆的元素。所謂反覆,即不能有兩個相等(注意。不是不過一樣)的對象。即若是Set集合中有了一個A對象。現在我要向Set集合再存入一個B對象。但B對象與A對象equals相等。則B對象存儲不進去,因此,Set集合的add方法有一個boolean的返回值。當集合中沒有某個元素。此時add方法可成功增長該元素時,則返回true,當集合含有與某個元素equals相等的元素時。此時add方法沒法增長該元素,返回結果爲false。
Set取元素時,無法說取第幾個,只能以Iterator接口取得所有的元素,再逐一遍歷各個元素。
List表示有前後順序的集合。注意,不是那種按年齡、按大小、按價格之類的排序。當咱們屢次調用add(Obj e)方法時。每次增長的對象就像火車站買票有排隊順序同樣,按先來後到的順序排序。有時候。也可以插隊,即調用add(int index,Obj e)方法。就可以指定當前對象在集合中的存放位置。一個對象可以被重複存儲進List中,每調用一次add方法,這個對象就被插入進集合中一次。事實上。並不是把這個對象自己存儲進了集合中,而是在集合中用一個索引變量指向這個對象,當這個對象被add屢次時。即至關於集合中有多個索引指向了這個對象,如圖x所看到的。List除了可以以Iterator接口取得所有的元素,再逐一遍歷各個元素以外,還可以調用get(index i)來明白說明取第幾個。
Map與List和Set不一樣。它是雙列的集合,當中有put方法,定義例如如下:put(obj key,objvalue)。每次存儲時。要存儲一對key/value。不能存儲反覆的key。這個反覆的規則也是按equals比較相等。取則可以依據key得到相應的value,即get(Object key)返回值爲key所相應的value。另外,也可以得到所有的key的結合,還可以得到所有的value的結合。還可以得到key和value組合成的Map.Entry對象的集合。
List 以特定次序來持有元素。可有反覆元素。Set沒法擁有反覆元素,內部排序。Map保存key-value值,value可多值。
HashSet依照hashcode值的某種運算方式進行存儲。而不是直接按hashCode值的大小進行存儲。好比,"abc"---> 78,"def" ---> 62,"xyz" ---> 65在hashSet中的存儲順序不是62,65,78,這些問題感謝曾經一個叫崔健的學員提出。最後經過查看源代碼給他解釋清楚,看本次培訓學員其中有多少能看懂源代碼。
LinkedHashSet按插入的順序存儲,那被存儲對象的hashcode方法還有什麼做用呢?學員想一想!hashset集合比較兩個對象是否相等。首先看hashcode方法是否相等,而後看equals方法是否相等。new兩個Student插入到HashSet中。看HashSet的size。實現hashcode和equals方法後再看size。
同一個對象可以在Vector中增長屢次。往集合裏面加元素,至關於集合裏用一根繩子鏈接到了目標對象。往HashSet中卻加不了屢次的。
64、說出ArrayList,Vector, LinkedList的存儲性能和特性
ArrayList和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便添加和插入元素,它們都贊成直接按序號索引元素。但是插入元素要涉及數組元素移動等內存操做,因此索引數據快而插入數據慢,Vector由於使用了synchronized方法(線程安全),一般性能上較ArrayList差,而LinkedList使用雙向鏈表實現存儲。按序號索引數據需要進行前向或後向遍歷。但是插入數據時僅僅需要記錄本項的先後項就能夠,因此插入速度較快。
LinkedList也是線程不安全的,LinkedList提供了一些方法,使得LinkedList可以被看成堆棧和隊列來使用。
65、去掉一個Vector集合中反覆的元素
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);
66、Collection和 Collections的差異。
Collection是集合類的上級接口,繼承與他的接口主要有Set和List.
Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各類集合的搜索、排序、線程安全化等操做。
67、Set裏的元素是不能反覆的,那麼用什麼方法來區分反覆與否呢?是用==仍是equals()?它們有何差異?
Set裏的元素是不能反覆的,元素反覆與否是使用equals()方法進行推斷的。
equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,爲的是當兩個分離的對象的內容和類型相配的話,返回真值。
最常用的集合類是 List 和 Map。
List的詳細實現包含 ArrayList和 Vector,它們是可變大小的列表,比較適合構建、存儲和操做不論什麼類型對象的元素列表。
List適用於按數值索引訪問元素的情形。
Map 提供了一個更通用的元素存儲方法。 Map集合類用於存儲元素對(稱做"鍵"和"值")。當中每個鍵映射到一個值。
ArrayList/VectoràList
àCollection
HashSet/TreeSetàSet
PropetiesàHashTable
àMap
Treemap/HashMap
我記的不是方法名,而是思想。我知道它們都有增刪改查的方法。但這些方法的詳細名稱,我記得不是很是清楚,對於set,大概的方法是add,remove, contains。對於map。大概的方法就是put,remove,contains等,因爲,我僅僅要在eclispe下按點操做符。很是天然的這些方法就出來了。我記住的一些思想就是List類會有get(int index)這個方案,因爲它可以按順序取元素。而set類中沒有get(int index)這個方案。List和set都可以迭代出所有元素,迭代時先要獲得一個iterator對象,因此,set和list類都有一個iterator方法,用於返回那個iterator對象。
map可以返回三個集合,一個是返回所有的key的集合,另一個返回的是所有value的集合。再一個返回的key和value組合成的EntrySet對象的集合,map也有get方法。參數是key,返回值是key相應的value。
69、兩個對象值一樣(x.equals(y) == true)。但卻可有不一樣的hash code,這句話對不正確?
對。
假設對象要保存在HashSet或HashMap中,它們的equals相等。那麼,它們的hashcode值就必須相等。
假設不是要保存在HashSet或HashMap,則與hashcode沒有什麼關係了,這時候hashcode不等是可以的。好比arrayList存儲的對象就不用實現hashcode,固然,咱們沒有理由不實現,一般都會去實現的。
70、TreeSet裏面放對象,假設同一時候放入了父類和子類的實例對象。那比較時使用的是父類的compareTo方法。仍是使用的子類的compareTo方法,仍是拋異常!
(應該是沒有針對問題的確切的答案,當前的add方法放入的是哪一個對象,就調用哪一個對象的compareTo方法。至於這個compareTo方法怎麼作,就看當前這個對象的類中是怎樣編寫這種方法的)
實驗代碼:
publicclass ParentimplementsComparable {
private int age = 0;
public Parent(int age){
this.age = age;
}
public int compareTo(Object o){
// TODO Auto-generated method stub
System.out.println("method ofparent");
Parent o1 = (Parent)o;
returnage>o1.age?
1:age<o1.age?-1:0;
}
}
publicclass Childextends Parent {
public Child(){
super(3);
}
public int compareTo(Object o){
// TODO Auto-generated methodstub
System.out.println("methodof child");
// Child o1 = (Child)o;
return 1;
}
}
publicclass TreeSetTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
TreeSet set = new TreeSet();
set.add(newParent(3));
set.add(new Child());
set.add(newParent(4));
System.out.println(set.size());
}
}
71、說出一些常用的類,包。接口,請各舉5個
要讓人家感受你對java ee開發很是熟,因此,不能只只列core java中的那些東西。要多列你在作ssh項目中涉及的那些東西。
就寫你近期寫的那些程序中涉及的那些類。
常用的類:BufferedReader BufferedWriter FileReader FileWirter String Integer
java.util.Date。System,Class,List,HashMap
常用的包:java.lang java.io java.util java.sql,javax.servlet,org.apache.strtuts.action,org.hibernate
常用的接口:Remote List Map Document NodeList,Servlet,HttpServletRequest,HttpServletResponse,Transaction(Hibernate)、Session(Hibernate),HttpSession
72、java中有幾種類型的流?JDK爲每種類型的流提供了一些抽象類以供繼承,請說出他們各自是哪些類?
字節流。字符流。字節流繼承於InputStream OutputStream,字符流繼承於InputStreamReaderOutputStreamWriter。在java.io包中還有更多的流,主要是爲了提升性能和使用方便。
73、字節流與字符流的差異
要把一片二進制數據數據逐一輸出到某個設備中,或者從某個設備中逐一讀取一片二進制數據,不管輸入輸出設備是什麼,咱們要用統一的方式來完畢這些操做,用一種抽象的方式進行描寫敘述。這個抽象描寫敘述方式起名爲IO流,相應的抽象類爲OutputStream和InputStream。不一樣的實現類就表明不一樣的輸入和輸出設備。它們都是針對字節進行操做的。
在應用中,經常要全然是字符的一段文本輸出去或讀進來,用字節流可以嗎?計算機中的一切終於都是二進制的字節形式存在。對於「中國」這些字符,首先要獲得其相應的字節,而後將字節寫入到輸出流。
讀取時。首先讀到的是字節,可是咱們要把它顯示爲字符,咱們需要將字節轉換成字符。
由於這種需求很是普遍。人家專門提供了字符流的包裝類。
底層設備永遠僅僅接受字節數據,有時候要寫字符串究竟層設備,需要將字符串轉成字節再進行寫入。
字符流是字節流的包裝,字符流則是直接接受字符串,它內部將串轉成字節。再寫入底層設備,這爲咱們向IO設別寫入或讀取字符串提供了一點點方便。
字符向字節轉換時。要注意編碼的問題,因爲字符串轉成字節數組,
事實上是轉成該字符的某種編碼的字節形式,讀取也是反之的道理。
解說字節流與字符流關係的代碼案例:
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
public class IOTest {
public static void main(String[]args) throws Exception {
String str = "中國人";
/*FileOutputStreamfos = newFileOutputStream("1.txt");
fos.write(str.getBytes("UTF-8"));
fos.close();*/
/*FileWriter fw =new FileWriter("1.txt");
fw.write(str);
fw.close();*/
PrintWriter pw =new PrintWriter("1.txt","utf-8");
pw.write(str);
pw.close();
/*FileReader fr =new FileReader("1.txt");
char[] buf = newchar[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len);
System.out.println(myStr);*/
/*FileInputStreamfr = new FileInputStream("1.txt");
byte[] buf = newbyte[1024];
int len =fr.read(buf);
String myStr = newString(buf,0,len,"UTF-8");
System.out.println(myStr);*/
BufferedReader br =new BufferedReader(
newInputStreamReader(
newFileInputStream("1.txt"),"UTF-8"
)
);
String myStr =br.readLine();
br.close();
System.out.println(myStr);
}
}
74、什麼是java序列化。怎樣實現java序列化?或者請解釋Serializable接口的做用。
咱們有時候將一個java對象變成字節流的形式傳出去或者從一個字節流中恢復成一個java對象。好比,要將java對象存儲到硬盤或者傳送給網絡上的其它計算機。這個過程咱們可以本身寫代碼去把一個java對象變成某個格式的字節流再傳輸,但是。jre自己就提供了這樣的支持,咱們可以調用OutputStream的writeObject方法來作,假設要讓java幫咱們作,要被傳輸的對象必須實現serializable接口,這樣。javac編譯時就會進行特殊處理。編譯的類才幹夠被writeObject方法操做,這就是所謂的序列化。
需要被序列化的類必須實現Serializable接口,該接口是一個mini接口,當中沒有需要實現的方法。implementsSerializable僅僅是爲了標註該對象是可被序列化的。
好比。在web開發中。假設對象被保存在了Session中。tomcat在從新啓動時要把Session對象序列化到硬盤,這個對象就必須實現Serializable接口。假設對象要通過分佈式系統進行網絡傳輸或經過rmi等遠程調用,這就需要在網絡上傳輸對象,被傳輸的對象就必須實現Serializable接口。
75、描寫敘述一下JVM載入class文件的原理機制?
JVM中類的裝載是由ClassLoader和它的子類來實現的,Java ClassLoader是一個重要的Java執行時系統組件。
它負責在執行時查找和裝入類文件的類。
76、heap和stack有什麼差異。
java的內存分爲兩類,一類是棧內存,一類是堆內存。棧內存是指程序進入一個方法時,會爲這種方法單獨分配一塊私屬存儲空間。用於存儲這種方法內部的局部變量。當這種方法結束時。分配給這種方法的棧會釋放。這個棧中的變量也將隨之釋放。
堆是與棧做用不一樣的內存,通常用於存放不放在當前方法棧中的那些數據,好比。使用new建立的對象都放在堆裏,因此,它不會隨方法的結束而消失。方法中的局部變量使用final修飾後,放在堆中。而不是棧中。
77、GC是什麼?
爲何要有GC?
GC是垃圾收集的意思(Gabage Collection),內存處理是編程人員easy出現故障的地方,忘記或者錯誤的內存回收會致使程序或系統的不穩定甚至崩潰。Java提供的GC功能可以本身主動監測對象是否超過做用域從而達到本身主動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操做方法。
78、垃圾回收的長處和原理。並考慮2種回收機制。
Java語言中一個顯著的特色就是引入了垃圾回收機制,使c++程序猿最頭疼的內存管理的問題迎刃而解,它使得Java程序猿在編敲代碼的時候再也不需要考慮內存管理。由於有個垃圾回收機制,Java中的對象再也不有"做用域"的概念,僅僅有對象的引用纔有"做用域"。垃圾回收可以有效的防止內存泄露。有效的使用可以使用的內存。垃圾回收器通常是做爲一個單獨的低級別的線程執行,不可預知的狀況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程序猿不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。
回收機制有分代複製垃圾回收和標記垃圾回收。增量垃圾回收。
79、垃圾回收器的基本原理是什麼?垃圾回收器可以當即回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?
對於GC來講,當程序猿建立對象時。GC就開始監控這個對象的地址、大小以及使用狀況。一般,GC採用有向圖的方式記錄和管理堆(heap)中的所有對象。經過這樣的方式肯定哪些對象是"可達的"。哪些對象是"不可達的"。
當GC肯定一些對象爲"不可達"時,GC就有責任回收這些內存空間。可以。
程序猿可以手動運行System.gc(),通知GC運行。但是Java語言規範並不保證GC必定會運行。
80、何時用assert。
assertion(斷言)在軟件開發中是一種常用的調試方式。很是多開發語言中都支持這樣的機制。在實現中,assertion就是在程序中的一條語句,它對一個boolean表達式進行檢查。一個正確程序必須保證這個boolean表達式的值爲true;假設該值爲false,說明程序已經處於不對的狀態下,assert將給出警告或退出。通常來講,assertion用於保證程序最基本、關鍵的正確性。assertion檢查一般在開發和測試時開啓。
爲了提升性能。在軟件公佈後。assertion檢查通常是關閉的。
package com.huawei.interview;
publicclass AssertTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
int i = 0;
for(i=0;i<5;i++)
{
System.out.println(i);
}
//若是程序不當心多了一句--i;
--i;
assert i==5;
}
}
81、java中會存在內存泄漏嗎,請簡單描寫敘述。
所謂內存泄露就是指一個再也不被程序使用的對象或變量一直被佔領在內存中。java中有垃圾回收機制,它可以保證一對象再也不被引用的時候,即對象編程了孤兒的時候。對象將本身主動被垃圾回收器從內存中清除掉。
由於Java使用有向圖的方式進行垃圾回收管理。可以消除引用循環的問題,好比有兩個對象。相互引用。僅僅要它們和根進程不可達的。那麼GC也是可以回收它們的。好比如下的代碼可以看到這樣的狀況的內存回收:
package com.huawei.interview;
import java.io.IOException;
publicclass GarbageTest {
/**
* @paramargs
* @throwsIOException
*/
public static voidmain(String[] args)throws IOException {
// TODO Auto-generated method stub
try {
gcTest();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("hasexited gcTest!");
System.in.read();
System.in.read();
System.out.println("out begingc!");
for(int i=0;i<100;i++)
{
System.gc();
System.in.read();
System.in.read();
}
}
private static voidgcTest()throws IOException {
System.in.read();
System.in.read();
Person p1 = new Person();
System.in.read();
System.in.read();
Person p2 = new Person();
p1.setMate(p2);
p2.setMate(p1);
System.out.println("beforeexit gctest!");
System.in.read();
System.in.read();
System.gc();
System.out.println("exitgctest!");
}
private static classPerson
{
byte[] data =new byte[20000000];
Person mate = null;
public void setMate(Personother)
{
mate = other;
}
}
}
java中的內存泄露的狀況:長生命週期的對象持有短生命週期對象的引用就很是可能發生內存泄露,雖然短生命週期對象已經再也不需要,但是因爲長生命週期對象持有它的引用而致使不能被回收,這就是java中內存泄露的發生場景,通俗地說。就是程序猿可能建立了一個對象。之後一直再也不使用這個對象,這個對象卻一直被引用。即這個對象無用但是卻沒法被垃圾回收器回收的。這就是java中可能出現內存泄露的狀況,好比。緩存系統,咱們載入了一個對象放在緩存中(好比放在一個全局map對象中),而後一直再也不使用它,這個對象一直被緩存引用,但卻再也不被使用。
檢查java中的內存泄露,必定要讓程序將各類分支狀況都完整運行到程序結束,而後看某個對象是否被使用過。假設沒有,則才幹斷定這個對象屬於內存泄露。
假設一個外部類的實例對象的方法返回了一個內部類的實例對象。這個內部類對象被長期引用了。即便那個外部類實例對象再也不被使用,但由於內部類持久外部類的實例對象,這個外部類對象將不會被垃圾回收,這也會形成內存泄露。
如下內容來自於網上(主要特色就是清空堆棧中的某個元素,並不是完全把它從數組中拿掉。而是把存儲的總數下降。本人寫得可以比這個好。在拿掉某個元素時,順便也讓它從數組中消失。將那個元素所在的位置的值設置爲null就能夠):
我實在想不到比那個堆棧更經典的樣例了,以至於我還要引用別人的樣例,如下的樣例不是我想到的,是書上看到的,固然假設沒有在書上看到,可能過一段時間我本身也想的到,可是那時我說是我本身想到的也沒有人相信的。
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(elements.length == size){
Object[] oldElements = elements;
elements = new Object[2 * elements.length+1];
System.arraycopy(oldElements,0, elements, 0, size);
}
}
}
上面的原理應該很是easy,假如堆棧加了10個元素。而後全部彈出來,儘管堆棧是空的。沒有咱們要的東西,但是這是個對象是沒法回收的,這個才符合了內存泄露的兩個條件:無用。沒法回收。
但是就是存在這種東西也不必定會致使什麼樣的後果,假設這個堆棧用的比較少。也就浪費了幾個K內存而已。反正咱們的內存都上G了,哪裏會有什麼影響。再說這個東西很是快就會被回收的,有什麼關係。
如下看兩個樣例。
樣例1
public class Bad{
public static Stack s=Stack();
static{
s.push(new Object());
s.pop(); //這裏有一個對象發生內存泄露
s.push(new Object()); //上面的對象可以被回收了,等因而自愈了
}
}
因爲是static。就一直存在到程序退出,但是咱們也可以看到它有自愈功能,就是說假設你的Stack最多有100個對象。那麼最多也就僅僅有100個對象沒法被回收事實上這個應該很是easy理解,Stack內部持有100個引用,最壞的狀況就是他們都是沒用的,因爲咱們一旦放新的進取,曾經的引用天然消失!
內存泄露的第二種狀況:當一個對象被存儲進HashSet集合中之後,就不能改動這個對象中的那些參與計算哈希值的字段了,不然。對象改動後的哈希值與最初存儲進HashSet集合中時的哈希值就不一樣了,在這樣的狀況下。即便在contains方法使用該對象的當前引用做爲的參數去HashSet集合中檢索對象,也將返回找不到對象的結果,這也會致使沒法從HashSet集合中單獨刪除當前對象。形成內存泄露。
82、能不能本身寫個類。也叫java.lang.String?
可以。但在應用的時候,需要用本身的類載入器去載入,不然,系統的類載入器永遠僅僅是去載入jre.jar包中的那個java.lang.String。由於在tomcat的web應用程序中,都是由webapp本身的類載入器先本身載入WEB-INF/classess文件夾中的類,而後才託付上級的類載入器載入,假設咱們在tomcat的web應用程序中寫一個java.lang.String,這時候Servlet程序載入的就是咱們本身寫的java.lang.String。但是這麼幹就會出很是多潛在的問題,原來所有用了java.lang.String類的都將出現故障。
儘管java提供了endorsed技術,能夠覆蓋jdk中的某些類,詳細作法是….。但是,能夠被覆蓋的類是有限制範圍,反正不包含java.lang這種包中的類。
(如下的好比主要是便於你們學習理解僅僅用,不要做爲答案的一部分,不然。人家懷疑是題目泄露了)好比,執行如下的程序:
package java.lang;
publicclass String {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
System.out.println("string");
}
}
報告的錯誤例如如下:
java.lang.NoSuchMethodError:main
Exception inthread "main"
這是因爲載入了jre自帶的java.lang.String,而該類中沒有main方法。
83. Java代碼查錯
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}
大俠們,這有何錯誤?
答案: 錯。abstract method必須以分號結尾,且不帶花括號。
2.
public class Something {
void doSomething () {
private String s = "";
int l = s.length();
}
}
有錯嗎?
答案: 錯。
局部變量前不能放置不論什麼訪問修飾符 (private,public。和protected)。
final可以用來修飾局部變量
(final如同abstract和strictfp。都是非訪問修飾符,strictfp僅僅能修飾class和method而非variable)。
3.
abstract class Something {
private abstract String doSomething ();
}
這好像沒什麼錯吧?
答案: 錯。
abstract的methods不能以private修飾。abstract的methods就是讓子類implement(實現)詳細細節的。怎麼可以用private把abstract
method封鎖起來呢? (同理。abstract method前不能加final)。
4.
public class Something {
public int addOne(final int x) {
return ++x;
}
}
這個比較明顯。
答案: 錯。
int x被修飾成final,意味着x不能在addOne method中被改動。
5.
public class Something {
public static void main(String[] args) {
Other o = new Other();
new Something().addOne(o);
}
public void addOne(final Other o) {
o.i++;
}
}
class Other {
public int i;
}
和上面的很是類似。都是關於final的問題,這有錯嗎?
答案: 正確。在addOne method中,參數o被修飾成final。假設在addOne method裏咱們改動了o的reference
(比方: o = new Other();)。那麼如同上例這題也是錯的。但這裏改動的是o的member vairable
(成員變量)。而o的reference並無改變。
6.
class Something {
int i;
public void doSomething() {
System.out.println("i = "+ i);
}
}
有什麼錯呢?
看不出來啊。
答案: 正確。輸出的是"i = 0"。
int i屬於instant variable (實例變量,或叫成員變量)。instant variable有default value。int的default value是0。
7.
class Something {
final int i;
public void doSomething() {
System.out.println("i = "+ i);
}
}
和上面一題僅僅有一個地方不一樣。就是多了一個final。這難道就錯了嗎?
答案: 錯。final int i是個final的instant variable (實例變量,或叫成員變量)。final的instant variable沒有default value,必須在constructor (構造器)結束以前被賦予一個明白的值。
可以改動爲"final int i =0;"。
8.
public class Something {
public static void main(String[] args) {
Something s = new Something();
System.out.println("s.doSomething() returns " + doSomething());
}
public String doSomething() {
return "Do something ...";
}
}
看上去很是完美。
答案: 錯。看上去在main裏call doSomething沒有什麼問題,畢竟兩個methods都在同一個class裏。但細緻看,main是static的。
static method不能直接call non-staticmethods。
可改爲"System.out.println("s.doSomething()returns " + s.doSomething());"。同理,static method不能訪問non-static instant variable。
9.
此處,Something類的文件名稱叫OtherThing.java
class Something {
private static void main(String[] something_to_do){
System.out.println("Dosomething ...");
}
}
這個好像很是明顯。
答案: 正確。歷來沒有人說過Java的Class名字必須和其文件名稱一樣。但public class的名字必須和文件名稱一樣。
10.
interface A{
int x = 0;
}
class B{
int x =1;
}
class C extends B implements A {
public void pX(){
System.out.println(x);
}
public static void main(String[] args) {
new C().pX();
}
}
答案:錯誤。在編譯時會錯誤發生(錯誤描寫敘述不一樣的JVM有不一樣的信息。意思就是未明白的x調用。兩個x都匹配(就象在同一時候import java.util和java.sql兩個包時直接聲明Date同樣)。
對於父類的變量,可以用super.x來明白,而接口的屬性默認隱含爲 public staticfinal.因此可以經過A.x來明白。
11.
interface Playable {
void play();
}
interface Bounceable {
void play();
}
interface Rollable extends Playable, Bounceable {
Ball ball = new Ball("PingPang");
}
class Ball implements Rollable {
private String name;
public String getName() {
return name;
}
public Ball(String name) {
this.name =name;
}
public void play() {
ball = newBall("Football");
System.out.println(ball.getName());
}
}
這個錯誤不easy發現。
答案: 錯。"interfaceRollable extends Playable, Bounceable"沒有問題。interface可繼承多個interfaces,因此這裏沒錯。問題出在interface Rollable裏的"Ball ball =new Ball("PingPang");"。
不論什麼在interface裏聲明的interface variable (接口變量。也可稱成員變量),默以爲public static final。
也就是說"Ball ball = new Ball("PingPang");"其實是"public staticfinal Ball ball = new Ball("PingPang");"。
在Ball類的Play()方法中。"ball = newBall("Football");"改變了ball的reference,而這裏的ball來自Rollable interface,Rollable interface裏的ball是public static final的,final的object是不能被改變reference的。所以編譯器將在"ball = newBall("Football");"這裏顯示有錯。
二.算法與編程
1、編寫一個程序,將a.txt文件裏的單詞與b.txt文件裏的單詞交替合併到c.txt文件裏,a.txt文件裏的單詞用回車符分隔,b.txt文件裏用回車或空格進行分隔。
答:
packagecn.itcast;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
public class MainClass{
public static voidmain(String[] args) throws Exception{
FileManager a= new FileManager("a.txt",new char[]{'\n'});
FileManager b= new FileManager("b.txt",new char[]{'\n',' '});
FileWriter c= new FileWriter("c.txt");
String aWord= null;
String bWord= null;
while((aWord= a.nextWord()) !=null ){
c.write(aWord+ "\n");
bWord= b.nextWord();
if(bWord!= null)
c.write(bWord+ "\n");
}
while((bWord= b.nextWord()) != null){
c.write(bWord+ "\n");
}
c.close();
}
}
class FileManager{
String[] words =null;
int pos = 0;
publicFileManager(String filename,char[] seperators) throws Exception{
File f = newFile(filename);
FileReaderreader = new FileReader(f);
char[] buf =new char[(int)f.length()];
int len =reader.read(buf);
Stringresults = new String(buf,0,len);
String regex= null;
if(seperators.length>1 ){
regex= "" + seperators[0] + "|" + seperators[1];
}else{
regex= "" + seperators[0];
}
words =results.split(regex);
}
public StringnextWord(){
if(pos ==words.length)
returnnull;
returnwords[pos++];
}
}
2、編寫一個程序,將d:\java文件夾下的所有.java文件拷貝到d:\jad文件夾下,並將原來文件的擴展名從.java改成.jad。
(你們正在作上面這道題。網上遲到的朋友也請作作這道題,找工做必須能編寫這些簡單問題的代碼!)
答:listFiles方法接受一個FileFilter對象。這個FileFilter對象就是過慮的策略對象,不一樣的人提供不一樣的FileFilter實現,即提供了不一樣的過濾策略。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Jad2Java {
public static voidmain(String[] args) throws Exception {
File srcDir =new File("java");
if(!(srcDir.exists()&& srcDir.isDirectory()))
thrownew Exception("文件夾不存在");
File[] files= srcDir.listFiles(
newFilenameFilter(){
publicboolean accept(File dir, String name) {
returnname.endsWith(".java");
}
}
);
System.out.println(files.length);
File destDir= new File("jad");
if(!destDir.exists())destDir.mkdir();
for(File f:files){
FileInputStream fis = new FileInputStream(f);
StringdestFileName = f.getName().replaceAll("\\.java$", ".jad");
FileOutputStreamfos = new FileOutputStream(new File(destDir,destFileName));
copy(fis,fos);
fis.close();
fos.close();
}
}
private static voidcopy(InputStream ips,OutputStream ops) throws Exception{
int len = 0;
byte[] buf =new byte[1024];
while((len =ips.read(buf)) != -1){
ops.write(buf,0,len);
}
}
}
由本題總結的思想及策略模式的解析:
1.
class jad2java{
1. 獲得某個文件夾下的所有的java文件集合
1.1 獲得文件夾 File srcDir = newFile("d:\\java");
1.2 獲得文件夾下的所有java文件:File[] files =srcDir.listFiles(new MyFileFilter());
1.3 僅僅想獲得.java的文件: class MyFileFilterimplememyts FileFilter{
publicboolean accept(File pathname){
returnpathname.getName().endsWith(".java")
}
}
2.將每個文件拷貝到另一個文件夾,並改擴展名
2.1 獲得目標文件夾,假設目標文件夾不存在。則建立之
2.2 依據源文件名稱獲得目標文件名稱,注意要用正則表達式,注意.的轉義。
2.3 依據表示文件夾的File和目標文件名稱的字符串。獲得表示目標文件的File。
//要在硬盤中準確地建立出一個文件,需要知道文件名稱和文件的文件夾。
2.4 將源文件的流拷貝成目標文件流,拷貝方法獨立成爲一個方法,方法的參數採用抽象流的形式。
//方法接受的參數類型儘可能面向父類。越抽象越好,這樣適應面更寬廣。
}
分析listFiles方法內部的策略模式實現原理
File[] listFiles(FileFilter filter){
File[] files =listFiles();
//ArraylistacceptedFilesList = new ArrayList();
File[] acceptedFiles= new File[files.length];
int pos = 0;
for(File file:files){
booleanaccepted = filter.accept(file);
if(accepted){
//acceptedFilesList.add(file);
acceptedFiles[pos++]= file;
}
}
Arrays.copyOf(acceptedFiles,pos);
//return(File[])accpetedFilesList.toArray();
}
3、編寫一個截取字符串的函數。輸入爲一個字符串和字節數,輸出爲按字節截取的字符串,但要保證漢字不被截取半個,如「我ABC」,4。應該截取「我AB」。輸入「我ABC漢DEF」,6。應該輸出「我ABC」。而不是「我ABC+漢的半個」。
答:
首先要了解中文字符有多種編碼及各類編碼的特徵。
若是n爲要截取的字節數。
public static voidmain(String[] args) throws Exception{
String str ="我a愛中華abc我愛傳智def';
String str ="我ABC漢";
int num =trimGBK(str.getBytes("GBK"),5);
System.out.println(str.substring(0,num));
}
public staticint trimGBK(byte[] buf,int n){
int num = 0;
booleanbChineseFirstHalf = false;
for(inti=0;i<n;i++)
{
if(buf[i]<0&& !bChineseFirstHalf){
bChineseFirstHalf= true;
}else{
num++;
bChineseFirstHalf= false;
}
}
return num;
}
4、有一個字符串,當中包括中文字符、英文字符和數字字符,請統計和打印出各個字符的個數。
答:哈哈。事實上包括中文字符、英文字符、數字字符原來是出題者放的煙霧彈。
String content = 「中國aadf的111薩bbb菲的zz薩菲」;
HashMap map = new HashMap();
for(int i=0;i<content.length;i++)
{
char c =content.charAt(i);
Integer num =map.get(c);
if(num == null)
num = 1;
else
num = num +1;
map.put(c,num);
}
for(Map.EntrySet entry : map)
{
system.out.println(entry.getkey()+ 「:」 + entry.getValue());
}
預計是當初面試的那個學員表述不清楚,問題很是多是:
若是一串字符如"aaaabbc中國1512"要分別統計英文字符的數量,中文字符的數量,和數字字符的數量,若是字符中沒有中文字符、英文字符、數字字符以外的其它特殊字符。
int engishCount;
int chineseCount;
int digitCount;
for(int i=0;i<str.length;i++)
{
charch = str.charAt(i);
if(ch>=’0’&& ch<=’9’)
{
digitCount++
}
elseif((ch>=’a’&& ch<=’z’) || (ch>=’A’ && ch<=’Z’))
{
engishCount++;
}
else
{
chineseCount++;
}
}
System.out.println(……………);
5、說明生活中遇到的二叉樹。用java實現二叉樹
這是組合設計模式。
我有很是多個(若是10萬個)數據要保存起來。之後還需要從保存的這些數據中檢索是否存在某個數據,(我想說出二叉樹的優勢,該怎麼說呢?那就是說別人的缺點),假如存在數組中,那麼,碰巧要找的數字位於99999那個地方,那查找的速度將很是慢。因爲要從第1個依次日後取,取出來後進行比較。平衡二叉樹(構建平衡二叉樹需要先排序。咱們這裏就不做考慮了)可以很是好地解決問題,但二叉樹的遍歷(前序。中序,後序)效率要比數組低很是多,原理例如如下圖:
代碼例如如下:
package com.huawei.interview;
publicclass Node {
public int value;
public Node left;
public Node right;
public void store(intvalue)
{
if(value<this.value)
{
if(left ==null)
{
left = new Node();
left.value=value;
}
else
{
left.store(value);
}
}
else if(value>this.value)
{
if(right ==null)
{
right = new Node();
right.value=value;
}
else
{
right.store(value);
}
}
}
public boolean find(intvalue)
{
System.out.println("happen" +this.value);
if(value ==this.value)
{
return true;
}
else if(value>this.value)
{
if(right ==null)returnfalse;
return right.find(value);
}else
{
if(left ==null)returnfalse;
return left.find(value);
}
}
public void preList()
{
System.out.print(this.value+ ",");
if(left!=null)left.preList();
if(right!=null) right.preList();
}
public void middleList()
{
if(left!=null)left.preList();
System.out.print(this.value+ ",");
if(right!=null)right.preList();
}
public void afterList()
{
if(left!=null)left.preList();
if(right!=null)right.preList();
System.out.print(this.value+ ",");
}
public static voidmain(String [] args)
{
int [] data =new int[20];
for(inti=0;i<data.length;i++)
{
data[i] = (int)(Math.random()*100)+ 1;
System.out.print(data[i] +",");
}
System.out.println();
Node root = new Node();
root.value = data[0];
for(inti=1;i<data.length;i++)
{
root.store(data[i]);
}
root.find(data[19]);
root.preList();
System.out.println();
root.middleList();
System.out.println();
root.afterList();
}
}
-----------------從新臨場寫的代碼---------------------------
importjava.util.Arrays;
importjava.util.Iterator;
public class Node{
private Node left;
private Node right;
private int value;
//private int num;
public Node(int value){
this.value = value;
}
public void add(int value){
if(value > this.value)
{
if(right != null)
right.add(value);
else
{
Node node = new Node(value);
right = node;
}
}
else{
if(left != null)
left.add(value);
else
{
Node node = new Node(value);
left = node;
}
}
}
public boolean find(int value){
if(value == this.value) return true;
else if(value > this.value){
if(right == null) return false;
else return right.find(value);
}else{
if(left == null) return false;
else return left.find(value);
}
}
public void display(){
System.out.println(value);
if(left != null) left.display();
if(right != null) right.display();
}
/*public Iterator iterator(){
}*/
public static void main(String[] args){
int[] values = new int[8];
for(int i=0;i<8;i++){
int num = (int)(Math.random() * 15);
//System.out.println(num);
//if(Arrays.binarySearch(values,num)<0)
if(!contains(values,num))
values[i] = num;
else
i--;
}
System.out.println(Arrays.toString(values));
Node root = new Node(values[0]);
for(int i=1;i<values.length;i++){
root.add(values[i]);
}
System.out.println(root.find(13));
root.display();
}
public static boolean contains(int [] arr,int value){
int i = 0;
for(;i<arr.length;i++){
if(arr[i] == value) return true;
}
return false;
}
}
6、從相似例如如下的文本文件裏讀取出所有的姓名,並打印出反覆的姓名和反覆的次數。並按反覆次數排序:
1,張三,28
2,李四,35
3,張三,28
4,王五,35
5,張三,28
6,李四,35
7,趙六,28
8,田七,35
程序代碼例如如下(答題要博得用人單位的喜歡。包名用該公司,面試前就提早查好該公司的網址。假設查不到。現場問也是可以的。
還要加上實現思路的凝視):
package com.huawei.interview;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
publicclass GetNameTest {
/**
* @paramargs
*/
public static voidmain(String[] args) {
// TODO Auto-generated method stub
//InputStream ips =GetNameTest.class.getResourceAsStream("/com/huawei/interview/info.txt");
//用上一行凝視的代碼和下一行的代碼都可以。因爲info.txt與GetNameTest類在同一包如下。因此,可以用如下的相對路徑形式
Map results = new HashMap();
InputStream ips = GetNameTest.class.getResourceAsStream("info.txt");
BufferedReader in = newBufferedReader(new InputStreamReader(ips));
String line = null;
try {
while((line=in.readLine())!=null)
{
dealLine(line,results);
}
sortResults(results);
} catch (IOException e) {
// TODO Auto-generated catchblock
e.printStackTrace();
}
}
static class User
{
public String name;
public Integer value;
public User(String name,Integervalue)
{
this.name = name;
this.value = value;
}
@Override
public booleanequals(Object obj) {
// TODO Auto-generated methodstub
//如下的代碼沒有運行。說明往treeset中添加數據時。不會使用到equals方法。
boolean result =super.equals(obj);
System.out.println(result);
return result;
}
}
private static voidsortResults(Map results) {
// TODO Auto-generated method stub
TreeSet sortedResults =newTreeSet(
new Comparator(){
public intcompare(Object o1, Object o2) {
// TODOAuto-generated method stub
User user1 = (User)o1;
User user2 = (User)o2;
/*假設compareTo返回結果0。則以爲兩個對象相等,新的對象不會添加到集合中去
* 因此,不能直接用如下的代碼,不然。那些個數一樣的其它姓名就打印不出來。
* */
//returnuser1.value-user2.value;
//returnuser1.value<user2.value?
-1:user1.value==user2.value?
0:1;
if(user1.value<user2.value)
{
return -1;
}else if(user1.value>user2.value)
{
return 1;
}else
{
returnuser1.name.compareTo(user2.name);
}
}
}
);
Iterator iterator =results.keySet().iterator();
while(iterator.hasNext())
{
String name = (String)iterator.next();
Integer value =(Integer)results.get(name);
if(value > 1)
{
sortedResults.add(newUser(name,value));
}
}
printResults(sortedResults);
}
private static voidprintResults(TreeSet sortedResults)
{
Iterator iterator = sortedResults.iterator();
while(iterator.hasNext())
{
User user = (User)iterator.next();
System.out.println(user.name +":" + user.value);
}
}
public static voiddealLine(String line,Map map)
{
if(!"".equals(line.trim()))
{
String [] results =line.split(",");
if(results.length == 3)
{
String name = results[1];
Integer value =(Integer)map.get(name);
if(value ==null)value = 0;
map.put(name,value + 1);
}
}
}
}
7、寫一個Singleton出來。
第一種:飽漢模式
public classSingleTon {
private SingleTon(){
}
//實例化放在靜態代碼塊裏可提升程序的運行效率,但也可能更佔用空間
private final static SingleTon instance =new SingleTon();
public static SingleTon getInstance(){
return instance;
}
}
另一種:飢漢模式
public classSingleTon {
private SingleTon(){}
private static instance = null;//newSingleTon();
public static synchronized SingleTongetInstance(){
if(instance == null)
instance = new SingleTon();
return instance;
}
}
第三種:用枚舉
public enum SingleTon{
ONE;
}
第三:更實際的應用(在什麼狀況用單例)
public classSequenceGenerator{
//如下是該類自身的業務功能代碼
private int count = 0;
public synchronized int getSequence(){
++count;
}
//如下是把該類變成單例的代碼
private SequenceGenerator(){}
private final static instance = newSequenceGenerator();
public static SingleTon getInstance(){
return instance;
}
}
第四:
public class MemoryDao
{
private HashMap map = new HashMap();
publicvoid add(Student stu1){
map.put(SequenceGenerator.getInstance().getSequence(),stu1);
}
//把MemoryDao變成單例
}
Singleton模式主要做用是保證在Java應用程序中,一個類Class僅僅有一個實例存在。
通常Singleton模式一般有幾種種形式:
第一種形式: 定義一個類,它的構造函數爲private的,它有一個static的private的該類變量,在類初始化時實例話。經過一個public的getInstance方法獲取對它的引用,繼而調用當中的方法。
public class Singleton {
private Singleton(){}
//在本身內部定義本身一個實例。是否是很是奇怪?
//注意這是private僅僅供內部調用
private staticSingleton instance = new Singleton();
//這裏提供了一個供外部訪問本class的靜態方法。可以直接訪問
public staticSingleton getInstance() {
return instance;
}
}
另一種形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這種方法比上面有所改進,不用每次都進行生成對象。僅僅是第一次
//使用時生成實例,提升了效率!
if (instance==null)
instance=new Singleton();
return instance;
}
}
其它形式:
定義一個類,它的構造函數爲private的,所有方法爲static的。
通常以爲第一種形式要更加安全些
8、遞歸算法題1
一個整數,大於0,不用循環和本地變量。依照n,2n。4n。8n的順序遞增。當值大於5000時。把值依照指定順序輸出來。
例:n=1237
則輸出爲:
1237。
2474,
4948。
9896。
9896,
4948,
2474,
1237,
提示:敲代碼時,先致謝按遞增方式的代碼。寫好遞增的之後,再添加考慮遞減部分。
public static void doubleNum(int n)
{
System.out.println(n);
if(n<=5000)
doubleNum(n*2);
System.out.println(n);
}
|
9、遞歸算法題2
第1我的10。第2個比第1我的大2歲,依次遞推。請用遞歸方式計算出第8我的多大?
package cn.itcast;
import java.util.Date;
publicclass A1 {
public static voidmain(String [] args)
{
System.out.println(computeAge(8));
}
public static int computeAge(intn)
{
if(n==1)return 10;
returncomputeAge(n-1) + 2;
}
}
public static voidtoBinary(int n,StringBuffer result)
{
if(n/2 != 0)
toBinary(n/2,result);
result.append(n%2);
}
10、排序都有哪幾種方法?請列舉。
用JAVA實現一個高速排序。
本人僅僅研究過冒泡排序、選擇排序和高速排序。如下是高速排序的代碼:
public class QuickSort {
/**
* 高速排序
* @param strDate
* @param left
* @param right
*/
public void quickSort(String[] strDate,int left,int right){
String middle,tempDate;
int i,j;
i=left;
j=right;
middle=strDate[(i+j)/2];
do{
while(strDate[i].compareTo(middle)<0&& i<right)
i++; //找出左邊比中間值大的數
while(strDate[j].compareTo(middle)>0&& j>left)
j--; //找出右邊比中間值小的數
if(i<=j){ //將左邊大的數和右邊小的數進行替換
tempDate=strDate[i];
strDate[i]=strDate[j];
strDate[j]=tempDate;
i++;
j--;
}
}while(i<=j); //當二者交錯時中止
if(i<right){
quickSort(strDate,i,right);//從
}
if(j>left){
quickSort(strDate,left,j);
}
}
/**
* @param args
*/
public static void main(String[] args){
String[] strVoid=newString[]{"11","66","22","0","55","22","0","32"};
QuickSort sort=new QuickSort();
sort.quickSort(strVoid,0,strVoid.length-1);
for(int i=0;i<strVoid.length;i++){
System.out.println(strVoid[i]+" ");
}
}
}
11、有數組a[n],用java代碼將數組元素順序顛倒
//用如下的也可以
//for(inti=0,int j=a.length-1;i<j;i++,j--)是否等效於for(int i=0;i<a.length/2;i++)呢?
importjava.util.Arrays;
public classSwapDemo{
public static void main(String[] args){
int [] a = new int[]{
(int)(Math.random() *1000),
(int)(Math.random() * 1000),
(int)(Math.random() *1000),
(int)(Math.random() *1000),
(int)(Math.random() * 1000)
};
System.out.println(a);
System.out.println(Arrays.toString(a));
swap(a);
System.out.println(Arrays.toString(a));
}
public static void swap(int a[]){
int len = a.length;
for(int i=0;i<len/2;i++){
int tmp = a[i];
a[i] = a[len-1-i];
a[len-1-i] = tmp;
}
}
}
12.金額轉換,阿拉伯數字的金額轉換成中國傳統的形式如:(¥1011)->(一千零一拾一元整)輸出。
去零的代碼:
returnsb.reverse().toString().replaceAll("零[拾佰仟]","零").replaceAll("零+萬","萬").replaceAll("零+元","元").replaceAll("零+","零");
public class RenMingBi {
/**
* @param args add by zxx ,Nov 29, 2008
*/
private static finalchar[] data = new char[]{
'零','壹','貳','叄','肆','伍','陸','柒','捌','玖'
};
private static finalchar[] units = new char[]{
'元','拾','佰','仟','萬','拾','佰','仟','億'
};
public static voidmain(String[] args) {
// TODOAuto-generated method stub
System.out.println(
convert(135689123));
}
public static Stringconvert(int money)
{
StringBuffersbf = new StringBuffer();
int unit = 0;
while(money!=0)
{
sbf.insert(0,units[unit++]);
intnumber = money%10;
sbf.insert(0,data[number]);
money/= 10;
}
returnsbf.toString();
}
}
三. html&JavaScript&ajax部分
1. 推斷第二個日期比第一個日期大
怎樣用腳本推斷用戶輸入的的字符串是如下的時間格式2004-11-21必須要保證用戶的輸入是此格式,並且是時間,比方說月份不大於12等等,另外我須要用戶輸入兩個。並且後一個要比前一個晚,僅僅贊成用JAVASCRIPT。請具體幫助做答,,
//這裏可用正則表達式推斷提早推斷一下格式,而後按下提取各時間字段內容
<script type="text/javascript">
window.onload =function()
{
//這麼寫是爲了實現js代碼與html代碼的分離。當我改動js時。不能影響html代碼。
document.getElementById("frm1").onsubmit=
function(){
vard1 = this.d1.value;
vard2 = this.d2.value;
if(!verifyDate(d1)) {alert("第一個日期格式不正確");return false;}
if(!verifyDate(d2)) {alert("第二個日期格式不正確");return false;}
if(!compareDate(d1,d2)){alert("第二個日期比第一日期小");return false;}
};
}
functioncompareDate(d1,d2)
{
var arrayD1= d1.split("-");
var date1 =new Date(arrayD1[0],arrayD1[1],arrayD1[2]);
var arrayD2= d2.split("-");
var date2 =new Date(arrayD2[0],arrayD2[1],arrayD2[2]);
if(date1> date2) return false;
return true;
}
functionverifyDate(d)
{
vardatePattern = /^\d{4}-(0?[1-9]|1[0-2])-(0?
[1-9]|[1-2]\d|3[0-1])$/;
returndatePattern.test(d);
}
</script>
<form id="frm1" action="xxx.html">
<input type="text" name="d1" />
<input type="text" name="d2" />
<input type="submit"/>
</form>
2. 用table顯示n條記錄。每3行換一次顏色,即1。2,3用紅色字體,4,5。6用綠色字體。7。8,9用紅顏色字體。
<body>
<table id="tbl">
<tr><td>1</td></tr>
<tr><td>2</td></tr>
<tr><td>3</td></tr>
<tr><td>4</td></tr>
<tr><td>5</td></tr>
<tr><td>6</td></tr>
<tr><td>7</td></tr>
<tr><td>8</td></tr>
<tr><td>9</td></tr>
<tr><td>10</td></tr>
</table>
</body>
<script type="text/javascript">
window.onload=function()
{
var tbl =document.getElementById("tbl");
rows =tbl.getElementsByTagName("tr");
for(i=0;i<rows.length;i++)
{
var j= parseInt(i/3);
if(j%2==0)rows[i].style.backgroundColor="#f00";
else rows[i].style.backgroundColor="#0f0";
}
}
</script>
3、HTML的 form提交以前怎樣驗證數值文本框的內容全部爲數字?不然的話提示用戶並終止提交?
<form onsubmit=’return chkForm(this)’>
<input type="text" name="d1"/>
<input type="submit"/>
</form>
<script type=」text/javascript」 />
function chkForm(this)
{
var value = thist.d1.value;
var len =value.length;
for(vari=0;i<len;i++)
{
if(value.charAt(i)>"9"|| value.charAt(i)<"0")
{
alert("含有非數字字符");
returnfalse;
}
}
return true;
}
</script>
4、請寫出用於校驗HTML文本框中輸入的內容全部爲數字的javascript代碼
<input type="text" id="d1" onblur=" chkNumber(this)"/>
<script type=」text/javascript」 />
function chkNumber(eleText)
{
var value =eleText.value;
var len =value.length;
for(vari=0;i<len;i++)
{
if(value.charAt(i)>"9"|| value.charAt(i)<"0")
{
alert("含有非數字字符");
eleText.focus();
break;
}
}
}
</script>
除了寫完代碼,還應該在網頁上寫出實驗步驟和在代碼中增長實現思路。讓面試官一看就明確你的意圖和檢查你的結果。
5、說說你用過那些ajax技術和框架,說說它們的差異
四. Java web部分
1、Tomcat的優化經驗
答:去掉對web.xml的監視。把jsp提早編輯成Servlet。
有富餘物理內存的狀況。加大tomcat使用的jvm的內存
2、HTTP請求的GET與POST方式的差異
答:servlet有良好的生存期的定義,包含載入和實例化、初始化、處理請求以及服務結束。
這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達。
3、解釋一下什麼是servlet;
答:servlet有良好的生存期的定義。包含載入和實例化、初始化、處理請求以及服務結束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達。
4、說一說Servlet的生命週期?
答:servlet有良好的生存期的定義。包含載入和實例化、初始化、處理請求以及服務結束。這個生存期由javax.servlet.Servlet接口的init,service和destroy方法表達。
Servlet被server實例化後,容器執行其init方法,請求到達時執行其service方法,service方法本身主動派遣執行與請求相應的doXXX方法(doGet,doPost)等,當server決定將實例銷燬的時候調用其destroy方法。
web容器載入servlet。生命週期開始。經過調用servlet的init()方法進行servlet的初始化。
經過調用service()方法實現。依據請求的不一樣調用不一樣的do***()方法。結束服務。web容器調用servlet的destroy()方法。
5、Servlet的基本架構
public class ServletName extends HttpServlet {
public void doPost(HttpServletRequest request,HttpServletResponse response) throws
ServletException, IOException {
}
public void doGet(HttpServletRequest request,HttpServletResponse response) throws
ServletException, IOException {
}
}
6、SERVLET API中forward()與redirect()的差異?
答:前者僅是容器中控制權的轉向,在client瀏覽器地址欄中不會顯示出轉向後的地址。後者則是全然的跳轉,瀏覽器將會獲得跳轉的地址。並又一次發送請求連接。這樣。從瀏覽器的地址欄中可以看到跳轉後的連接地址。
因此。前者更加高效,在前者可以知足需要時,儘可能使用forward()方法,並且。這樣也有助於隱藏實際的連接。
在有些狀況下,比方,需要跳轉到一個其餘server上的資源。則必須使用
sendRedirect()方法。
7、什麼狀況下調用doGet()和doPost()?
Jsp頁面中的FORM標籤裏的method屬性爲get時調用doGet(),爲post時調用doPost()。
8、Request對象的主要方法:
setAttribute(String name,Object):設置名字爲name的request的參數值
getAttribute(String name):返回由name指定的屬性值
getAttributeNames():返回request對象所有屬性的名字集合。結果是一個枚舉的實例
getCookies():返回client的所有Cookie對象,結果是一個Cookie數組
getCharacterEncoding():返回請求中的字符編碼方式
getContentLength():返回請求的Body的長度
getHeader(String name):得到HTTP協議定義的文件頭信息
getHeaders(String name):返回指定名字的request Header的所有值,結果是一個枚舉的實例
getHeaderNames():返回因此request Header的名字。結果是一個枚舉的實例
getInputStream():返回請求的輸入流,用於得到請求中的數據
getMethod():得到client向server端傳送數據的方法
getParameter(String name):得到client傳送給server端的有name指定的參數值
getParameterNames():得到client傳送給server端的所有參數的名字,結果是一個枚舉的實例
getParametervalues(String name):得到有name指定的參數的所有值
getProtocol():獲取client向server端傳送數據所根據的協議名稱
getQueryString():得到查詢字符串
getRequestURI():獲取發出請求字符串的client地址
getRemoteAddr():獲取client的IP地址
getRemoteHost():獲取client的名字
getSession([Boolean create]):返回和請求相關Session
getServerName():獲取server的名字
getServletPath():獲取client所請求的腳本文件的路徑
getServerPort():獲取server的port號
removeAttribute(String name):刪除請求中的一個屬性
9、forward和redirect的差異
forward是server請求資源,server直接訪問目標地址的URL,把那個URL的響應內容讀取過來,而後把這些內容再發給瀏覽器,瀏覽器根本不知道server發送的內容是從哪兒來的,因此它的地址欄中仍是原來的地址。
redirect就是服務端依據邏輯,發送一個狀態碼,告訴瀏覽器又一次去請求那個地址,通常來講瀏覽器會用剛纔請求的所有參數又一次請求。因此session,request參數都可以獲取。
10、request.getAttribute()和 request.getParameter()有何差異?
11. jsp有哪些內置對象?做用各自是什麼?
分別有什麼方法?
答:JSP共同擁有下面9個內置的對象:
request 用戶端請求,此請求會包括來自GET/POST請求的參數
response 網頁傳回用戶端的迴應
pageContext 網頁的屬性是在這裏管理
session 與請求有關的會話期
application servlet 正在運行的內容
out 用來傳送回應的輸出
config servlet的構架部件
page JSP網頁自己
exception 針對錯誤網頁,未捕捉的例外
request表示HttpServletRequest對象。它包括了有關瀏覽器請求的信息。並且提供了幾個用於獲取cookie, header,和session數據的實用的方法。
response表示HttpServletResponse對象,並提供了幾個用於設置送回瀏覽器的響應的方法(如cookies,頭信息等)
out對象是javax.jsp.JspWriter的一個實例,並提供了幾個方法使你能用於向瀏覽器回送輸出結果。
pageContext表示一個javax.servlet.jsp.PageContext對象。
它是用於方便存取各類範圍的名字空間、servlet相關的對象的API。並且包裝了通用的servlet相關功能的方法。
session表示一個請求的javax.servlet.http.HttpSession對象。
Session可以存貯用戶的狀態信息
applicaton 表示一個javax.servle.ServletContext對象。這有助於查找有關servlet引擎和servlet環境的信息
config表示一個javax.servlet.ServletConfig對象。
該對象用於存取servlet實例的初始化參數。
page表示從該頁面產生的一個servlet實例
12. jsp有哪些動做?做用各自是什麼?
(這個問題彷佛不重要,不明確爲什麼有此題)
答:JSP共同擁有下面6種基本動做
jsp:include:在頁面被請求的時候引入一個文件。
jsp:useBean:尋找或者實例化一個JavaBean。
jsp:setProperty:設置JavaBean的屬性。
jsp:getProperty:輸出某個JavaBean的屬性。
jsp:forward:把請求轉到一個新的頁面。
jsp:plugin:依據瀏覽器類型爲Java插件生成OBJECT或EMBED標記
13、JSP的常用指令
isErrorPage(可否使用Exception對象),isELIgnored(是否忽略表達式)
14. JSP中動態INCLUDE與靜態INCLUDE的差異?
答:動態INCLUDE用jsp:include動做實現
<jsp:include page=included.jsp flush=true />它老是會檢查所含文件裏的變化,適合用於包括動態頁面。並且可以帶參數靜態INCLUDE用include僞碼實現,定不會檢查所含文件的變化,適用於包括靜態頁面 <%@include file=included.htm %>
15、兩種跳轉方式各自是什麼?有什麼差異?
(如下的回答嚴重錯誤,應該是想問forward和sendRedirect的差異,畢竟出題的人不是專業搞文字藝術的人。可能表達能力並不見得很是強。用詞不必定精準,加之其自身的技術面也可能存在一些問題,不必定真正將他的意思表達清楚了,嚴格意思上來說,一些題目可能根本就無人能答,因此,答題時要掌握主動。僅僅要把本身知道的表達清楚就夠了,而不要去推敲原始題目的詳細含義是什麼,不要一味想着是在答題)
答:有兩種,分別爲:
<jsp:include page=included.jsp flush=true>
<jsp:forward page= nextpage.jsp/>
前者頁面不會轉向include所指的頁面,僅僅是顯示該頁的結果。主頁面仍是原來的頁面。運行完後還會回來,至關於函數調用。並且可以帶參數.後者全然轉向新頁面,不會再回來。至關於go to 語句。
16、頁面間對象傳遞的方法
request。session,application,cookie等
17、JSP和Servlet有哪些一樣點和不一樣點,他們之間的聯繫是什麼?