Java面試2

56、子線程循環(huán) 10 次所计,接著主線程循環(huán) 100柠辞,接著又回到子線程循環(huán) 10 次,

接著再回到主線程又循環(huán) 100主胧,如此循環(huán) 50 次叭首,請寫出程序。

最終的程序代碼如下:

public class 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;//這里相當于定義了控制該誰執(zhí)行的一個信號燈

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();

}

}

}

備注:不可能一上來就寫出上面的完整代碼踪栋,最初寫出來的代碼如下焙格,問題在于兩個線程的

代碼要參照同一個變量,即這兩個線程的代碼要共享數(shù)據(jù)己英,所以间螟,把這兩個線程的執(zhí)行代碼

搬到同一個類中去:

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中的并發(fā)庫來實現(xiàn)的:

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 框架的結(jié)構(gòu)

答:隨意發(fā)揮題损肛,天南海北誰便談厢破,只要讓別覺得你知識淵博,理解透徹即可治拿。

58摩泪、Collection 框架中實現(xiàn)比較要實現(xiàn)什么接口

comparable/comparator

59、ArrayList 和 Vector 的區(qū)別

答:

這兩個類都實現(xiàn)了 List 接口(List 接口繼承了 Collection 接口)劫谅,他們都是有序集合见坑,即存

儲在這兩個集合中的元素的位置都是有順序的,相當于一種動態(tài)的數(shù)組捏检,我們以后可以按位

置索引號取出某個元素荞驴,,并且其中的數(shù)據(jù)是允許重復(fù)的贯城,這是 HashSet 之類的集合的最大

不同處熊楼,HashSet 之類的集合不可以按索引號去檢索其中的元素,也不允許有重復(fù)的元素

(本來題目問的與 hashset 沒有任何關(guān)系能犯,但為了說清楚 ArrayList 與 Vector 的功能鲫骗,我們

使用對比方式犬耻,更有利于說明問題)。

接著才說 ArrayList 與 Vector 的區(qū)別执泰,這主要包括兩個方面:.

(1)同步性:

Vector 是線程安全的枕磁,也就是說是它的方法之間是線程同步的,而 ArrayList 是線程

序不安全的术吝,它的方法之間是線程不同步的计济。如果只有一個線程會訪問到集合,那最好是使

用 ArrayList顿苇,因為它不考慮線程安全峭咒,效率會高些;如果有多個線程會訪問到集合纪岁,那最

好是使用 Vector凑队,因為不需要我們自己再去考慮和編寫線程安全的代碼。

備注:對于 Vector&ArrayList幔翰、Hashtable&HashMap漩氨,要記住線程安全的問題,記住 Vector

與 Hashtable 是舊的遗增,是 java 一誕生就提供了的叫惊,它們是線程安全的,ArrayList 與 HashMap

是 java2時才提供的做修,它們是線程不安全的霍狰。所以,我們講課時先講老的饰及。

(2)數(shù)據(jù)增長:

ArrayList 與 Vector 都有一個初始的容量大小蔗坯,當存儲進它們里面的元素的個數(shù)超過

了容量時,就需要增加 ArrayList 與 Vector 的存儲空間燎含,每次要增加存儲空間時宾濒,不是只增

加一個存儲單元,而是增加多個存儲單元屏箍,每次增加的存儲單元的個數(shù)在內(nèi)存空間利用與程

序效率之間要取得一定的平衡绘梦。Vector 默認增長為原來兩倍,而 ArrayList 的增長策略在文

檔中沒有明確規(guī)定(從源代碼看到的是增長為原來的1.5倍)赴魁。ArrayList 與 Vector 都可以設(shè)

置初始的空間大小卸奉,Vector 還可以設(shè)置增長的空間大小,而 ArrayList 沒有提供設(shè)置增長空

間的方法颖御。

總結(jié):即 Vector 增長原來的一倍择卦,ArrayList 增加原來的0.5倍。

60郎嫁、HashMap 和 Hashtable 的區(qū)別

(條理上還需要整理秉继,也是先說相同點,再說不同點)

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 interface 的一個實現(xiàn)。

最大的不同是愕够,Hashtable 的方法是 Synchronize 的走贪,而 HashMap 不是,在多個線程訪問

Hashtable 時惑芭,不需要自己為它的方法實現(xiàn)同步坠狡,而 HashMap 就必須為之提供外同步。

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

就 HashMap 與 HashTable 主要從三方面來說。

一.歷史原因:Hashtable 是基于陳舊的 Dictionary 類的幻锁,HashMap 是 Java 1.2引進的 Map

接口的一個實現(xiàn)

二.同步性:Hashtable 是線程安全的凯亮,也就是說是同步的,而 HashMap 是線程序不安全的越败,

不是同步的

三.值:只有 HashMap 可以讓你將空值作為一個表的條目的 key 或 value

61触幼、List 和 Map 區(qū)別?

一個是存儲單列數(shù)據(jù)的集合,另一個是存儲鍵和值這樣的雙列數(shù)據(jù)的集合究飞,List 中存儲的數(shù)

據(jù)是有順序置谦,并且允許重復(fù);Map 中存儲的數(shù)據(jù)是沒有順序的亿傅,其鍵是不能重復(fù)的媒峡,它的

值是可以有重復(fù)的。

62葵擎、List, Set, Map 是否繼承自 Collection 接口?

List谅阿,Set 是,Map 不是

63、List签餐、Map寓涨、Set 三個接口,存取元素時氯檐,各有什么特點戒良?

這樣的題屬于隨意發(fā)揮題:這樣的題比較考水平,兩個方面的水平:一是要真正明白這些內(nèi)

容冠摄,二是要有較強的總結(jié)和表述能力糯崎。如果你明白,但表述不清楚河泳,在別人那里則等同于不

明白沃呢。

首先,List 與 Set 具有相似性拆挥,它們都是單列元素的集合薄霜,所以,它們有一個功共同的父接

口竿刁,叫 Collection黄锤。Set 里面不允許有重復(fù)的元素,所謂重復(fù)食拜,即不能有兩個相等(注意鸵熟,

不是僅僅是相同)的對象,即假設(shè) Set 集合中有了一個 A 對象负甸,現(xiàn)在我要向 Set 集合再存

入一個 B 對象流强,但 B 對象與 A 對象 equals 相等,則 B 對象存儲不進去呻待,所以打月,Set 集合的

add 方法有一個 boolean 的返回值,當集合中沒有某個元素蚕捉,此時 add 方法可成功加入該

元素時奏篙,則返回 true,當集合含有與某個元素 equals 相等的元素時迫淹,此時 add 方法無法加

入該元素秘通,返回結(jié)果為 false。Set 取元素時敛熬,沒法說取第幾個肺稀,只能以 Iterator 接口取得所

有的元素,再逐一遍歷各個元素应民。

List 表示有先后順序的集合话原,注意夕吻,不是那種按年齡、按大小繁仁、按價格之類的排序涉馅。

當我們多次調(diào)用 add(Obj e)方法時,每次加入的對象就像火車站買票有排隊順序一樣改备,按先

來后到的順序排序控漠。有時候,也可以插隊悬钳,即調(diào)用 add(int index,Obj e)方法,就可以指定當

前對象在集合中的存放位置偶翅。一個對象可以被反復(fù)存儲進 List 中默勾,每調(diào)用一次 add 方法,

這個對象就被插入進集合中一次聚谁,其實母剥,并不是把這個對象本身存儲進了集合中,而是在集

合中用一個索引變量指向這個對象形导,當這個對象被 add 多次時环疼,即相當于集合中有多個索

引指向了這個對象,如圖 x 所示朵耕。List 除了可以以 Iterator 接口取得所有的元素炫隶,再逐一遍

歷各個元素之外,還可以調(diào)用 get(index i)來明確說明取第幾個阎曹。

Map 與 List 和 Set 不同伪阶,它是雙列的集合,其中有 put 方法处嫌,定義如下:put(obj

key,objvalue)栅贴,每次存儲時,要存儲一對 key/value熏迹,不能存儲重復(fù)的 key檐薯,這個重復(fù)的規(guī)

則也是按 equals 比較相等。取則可以根據(jù) key 獲得相應(yīng)的 value注暗,即 get(Object key)返回

值為 key 所對應(yīng)的 value坛缕。另外,也可以獲得所有的 key 的結(jié)合友存,還可以獲得所有的 value

的結(jié)合祷膳,還可以獲得 key 和 value 組合成的 Map.Entry 對象的集合。

List 以特定次序來持有元素屡立,可有重復(fù)元素直晨。Set 無法擁有重復(fù)元素,內(nèi)部排序搀军。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捅暴,實現(xiàn) hashcode 和 equals 方法后再看 size。

同一個對象可以在 Vector 中加入多次咧纠。往集合里面加元素蓬痒,相當于集合里用一根繩子連接

到了目標對象。往 HashSet 中卻加不了多次的惧盹。

64乳幸、說出 ArrayList,Vector, LinkedList 的存儲性能和特性

ArrayList 和 Vector 都是使用數(shù)組方式存儲數(shù)據(jù),此數(shù)組元素數(shù)大于實際存儲的數(shù)據(jù)以便增

加和插入元素钧椰,它們都允許直接按序號索引元素粹断,但是插入元素要涉及數(shù)組元素移動等內(nèi)存

操作,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢嫡霞,Vector 由于使用了 synchronized 方法(線程安全)瓶埋,

通常性能上較 ArrayList 差,而 LinkedList 使用雙向鏈表實現(xiàn)存儲诊沪,按序號索引數(shù)據(jù)需要進

行前向或后向遍歷养筒,但是插入數(shù)據(jù)時只需要記錄本項的前后項即可,所以插入速度較快端姚。

LinkedList 也是線程不安全的晕粪,LinkedList 提供了一些方法,使得 LinkedList 可以被當作堆

棧和隊列來使用渐裸。

65捐名、去掉一個 Vector 集合中重復(fù)的元素

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 的區(qū)別。

Collection 是集合類的上級接口诀诊,繼承與他的接口主要有 Set 和 List.

Collections 是針對集合類的一個幫助類,他提供一系列靜態(tài)方法實現(xiàn)對各種集合的搜索阅嘶、

排序属瓣、線程安全化等操作。

67讯柔、Set 里的元素是不能重復(fù)的抡蛙,那么用什么方法來區(qū)分重復(fù)與否呢?是用==還

是 equals()?它們有何區(qū)別?

Set 里的元素是不能重復(fù)的,元素重復(fù)與否是使用 equals()方法進行判斷的磷杏。

equals()和==方法決定引用值是否指向同一對象 equals()在類中被覆蓋溜畅,為的是當兩個

分離的對象的內(nèi)容和類型相配的話,返回真值极祸。

68、你所知道的集合類都有哪些怠晴?主要方法遥金?

最常用的集合類是 List 和 Map。 List 的具體實現(xiàn)包括 ArrayList 和 Vector蒜田,它們是可變

大小的列表稿械,比較適合構(gòu)建、存儲和操作任何類型對象的元素列表冲粤。 List 適用于按數(shù)值索

引訪問元素的情形美莫。

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 方法,參數(shù)是 key府寒,返回值是 key 對應(yīng)的 value魁衙。

69、兩個對象值相同(x.equals(y) == true)株搔,但卻可有不同的 hash code剖淀,這句

話對不對?

對。

如果對象要保存在 HashSet 或 HashMap 中纤房,它們的 equals 相等纵隔,那么,它們的 hashcode

值就必須相等炮姨。

如果不是要保存在HashSet或HashMap捌刮,則與hashcode沒有什么關(guān)系了,這時候hashcode

不等是可以的舒岸,例如 arrayList 存儲的對象就不用實現(xiàn) hashcode绅作,當然,我們沒有理由不實

現(xiàn)吁津,通常都會去實現(xiàn)的棚蓄。

70、TreeSet 里面放對象碍脏,如果同時放入了父類和子類的實例對象梭依,那比較時使

用的是父類的 compareTo 方法,還是使用的子類的 compareTo 方法典尾,還是拋

異常役拴!

(應(yīng)該是沒有針對問題的確切的答案,當前的 add 方法放入的是哪個對象钾埂,就調(diào)用哪個對

象的 compareTo 方法河闰,至于這個 compareTo 方法怎么做科平,就看當前這個對象的類中是如何

編寫這個方法的)

實驗代碼:

public class 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;

return age>o1.age?1:age<o1.age?-1:0;

}

}

public class 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;

}

}

public class 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 開發(fā)很熟部念,所以弃酌,不能僅僅只列 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 為每種類型的流提供了一些抽象類以供繼承,

請說出他們分別是哪些類鬼佣?

字節(jié)流初嘹,字符流。字節(jié)流繼承于 InputStream OutputStream沮趣,字符流繼承于

InputStreamReaderOutputStreamWriter。在 java.io 包中還有許多其他的流坷随,主要是為了提

高性能和使用方便房铭。

73、字節(jié)流與字符流的區(qū)別

要把一片二進制數(shù)據(jù)數(shù)據(jù)逐一輸出到某個設(shè)備中温眉,或者從某個設(shè)備中逐一讀取一片

二進制數(shù)據(jù)缸匪,不管輸入輸出設(shè)備是什么,我們要用統(tǒng)一的方式來完成這些操作类溢,用一種抽象

的方式進行描述凌蔬,這個抽象描述方式起名為 IO 流,對應(yīng)的抽象類為 OutputStream 和

InputStream闯冷,不同的實現(xiàn)類就代表不同的輸入和輸出設(shè)備砂心,它們都是針對字節(jié)進行操作的。

在應(yīng)用中蛇耀,經(jīng)常要完全是字符的一段文本輸出去或讀進來辩诞,用字節(jié)流可以嗎?計算

機中的一切最終都是二進制的字節(jié)形式存在纺涤。對于“中國”這些字符译暂,首先要得到其對應(yīng)的字

節(jié)抠忘,然后將字節(jié)寫入到輸出流。讀取時外永,首先讀到的是字節(jié)崎脉,可是我們要把它顯示為字符,

我們需要將字節(jié)轉(zhuǎn)換成字符伯顶。由于這樣的需求很廣泛囚灼,人家專門提供了字符流的包裝類。

底層設(shè)備永遠只接受字節(jié)數(shù)據(jù)砾淌,有時候要寫字符串到底層設(shè)備啦撮,需要將字符串轉(zhuǎn)成字節(jié)再

進行寫入。字符流是字節(jié)流的包裝汪厨,字符流則是直接接受字符串赃春,它內(nèi)部將串轉(zhuǎn)成字節(jié),

再寫入底層設(shè)備劫乱,這為我們向 IO 設(shè)別寫入或讀取字符串提供了一點點方便织中。

字符向字節(jié)轉(zhuǎn)換時,要注意編碼的問題衷戈,因為字符串轉(zhuǎn)成字節(jié)數(shù)組狭吼,

其實是轉(zhuǎn)成該字符的某種編碼的字節(jié)形式,讀取也是反之的道理殖妇。

講解字節(jié)流與字符流關(guān)系的代碼案例:

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 序列化,如何實現(xiàn) java 序列化谦趣?或者請解釋 Serializable 接口

的作用疲吸。

我們有時候?qū)⒁粋€ java 對象變成字節(jié)流的形式傳出去或者從一個字節(jié)流中恢復(fù)成一個 java

對象,例如前鹅,要將 java 對象存儲到硬盤或者傳送給網(wǎng)絡(luò)上的其他計算機摘悴,這個過程我們可

以自己寫代碼去把一個 java 對象變成某個格式的字節(jié)流再傳輸,但是舰绘,jre 本身就提供了這

種支持蹂喻,我們可以調(diào)用 OutputStream 的 writeObject 方法來做,如果要讓 java 幫我們做捂寿,

要被傳輸?shù)膶ο蟊仨殞崿F(xiàn) serializable 接口口四,這樣,javac 編譯時就會進行特殊處理者蠕,編譯

的類才可以被 writeObject 方法操作窃祝,這就是所謂的序列化。需要被序列化的類必須實現(xiàn)

Serializable 接口,該接口是一個 mini 接口粪小,其中沒有需要實現(xiàn)的方法大磺,

implementsSerializable 只是為了標注該對象是可被序列化的。

例如探膊,在 web 開發(fā)中杠愧,如果對象被保存在了 Session 中,tomcat 在重啟時要把 Session 對

象序列化到硬盤逞壁,這個對象就必須實現(xiàn) Serializable 接口流济。如果對象要經(jīng)過分布式系統(tǒng)進行

網(wǎng)絡(luò)傳輸或通過 rmi 等遠程調(diào)用,這就需要在網(wǎng)絡(luò)上傳輸對象腌闯,被傳輸?shù)膶ο缶捅仨殞崿F(xiàn)

Serializable 接口绳瘟。

75、描述一下 JVM 加載 class 文件的原理機制?

JVM 中類的裝載是由 ClassLoader 和它的子類來實現(xiàn)的,Java ClassLoader 是一個重要的

Java 運行時系統(tǒng)組件姿骏。它負責在運行時查找和裝入類文件的類糖声。

76、heap 和 stack 有什么區(qū)別分瘦。

java 的內(nèi)存分為兩類蘸泻,一類是棧內(nèi)存,一類是堆內(nèi)存嘲玫。棧內(nèi)存是指程序進入一個方法時悦施,

會為這個方法單獨分配一塊私屬存儲空間,用于存儲這個方法內(nèi)部的局部變量去团,當這個方法

結(jié)束時抡诞,分配給這個方法的棧會釋放,這個棧中的變量也將隨之釋放土陪。

堆是與棧作用不同的內(nèi)存沐绒,一般用于存放不放在當前方法棧中的那些數(shù)據(jù),例如旺坠,使用 new

創(chuàng)建的對象都放在堆里,所以扮超,它不會隨方法的結(jié)束而消失取刃。方法中的局部變量使用 final

修飾后,放在堆中出刷,而不是棧中璧疗。

77、GC 是什么?為什么要有 GC?

GC 是垃圾收集的意思(Gabage Collection),內(nèi)存處理是編程人員容易出現(xiàn)問題的地方馁龟,

忘記或者錯誤的內(nèi)存回收會導致程序或系統(tǒng)的不穩(wěn)定甚至崩潰崩侠,Java 提供的 GC 功能可以

自動監(jiān)測對象是否超過作用域從而達到自動回收內(nèi)存的目的,Java 語言沒有提供釋放已分

配內(nèi)存的顯示操作方法坷檩。

78却音、垃圾回收的優(yōu)點和原理改抡。并考慮 2 種回收機制。

Java 語言中一個顯著的特點就是引入了垃圾回收機制系瓢,使 c++程序員最頭疼的內(nèi)存管理的

問題迎刃而解阿纤,它使得 Java 程序員在編寫程序的時候不再需要考慮內(nèi)存管理。由于有個垃

圾回收機制夷陋,Java 中的對象不再有"作用域"的概念欠拾,只有對象的引用才有"作用域"。垃圾回

收可以有效的防止內(nèi)存泄露骗绕,有效的使用可以使用的內(nèi)存藐窄。垃圾回收器通常是作為一個單獨

的低級別的線程運行,不可預(yù)知的情況下對內(nèi)存堆中已經(jīng)死亡的或者長時間沒有使用的對象

進行清楚和回收酬土,程序員不能實時的調(diào)用垃圾回收器對某個對象或所有對象進行垃圾回收荆忍。

回收機制有分代復(fù)制垃圾回收和標記垃圾回收,增量垃圾回收诺凡。

79东揣、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內(nèi)存嗎腹泌?有什么

辦法主動通知虛擬機進行垃圾回收嘶卧?

對于 GC 來說,當程序員創(chuàng)建對象時凉袱,GC 就開始監(jiān)控這個對象的地址芥吟、大小以及使用情況。

通常专甩,GC 采用有向圖的方式記錄和管理堆(heap)中的所有對象钟鸵。通過這種方式確定哪些對

象是"可達的",哪些對象是"不可達的"涤躲。當 GC 確定一些對象為"不可達"時棺耍,GC 就有責任回

收這些內(nèi)存空間≈钟#可以蒙袍。程序員可以手動執(zhí)行 System.gc(),通知 GC 運行嫩挤,但是 Java 語

言規(guī)范并不保證 GC 一定會執(zhí)行害幅。

80、什么時候用 assert岂昭。

assertion(斷言)在軟件開發(fā)中是一種常用的調(diào)試方式以现,很多開發(fā)語言中都支持這種機制。在

實現(xiàn)中,assertion 就是在程序中的一條語句邑遏,它對一個 boolean 表達式進行檢查佣赖,一個正

確程序必須保證這個 boolean 表達式的值為 true;如果該值為 false无宿,說明程序已經(jīng)處于不

正確的狀態(tài)下茵汰,assert 將給出警告或退出。一般來說孽鸡,assertion 用于保證程序最基本蹂午、關(guān)

鍵的正確性。assertion 檢查通常在開發(fā)和測試時開啟彬碱。為了提高性能豆胸,在軟件發(fā)布后,

assertion 檢查通常是關(guān)閉的巷疼。

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);

}

//假設(shè)程序不小心多了一句--i;

--i;

assert i==5;

}?

}

81晚胡、java 中會存在內(nèi)存泄漏嗎,請簡單描述嚼沿。

所謂內(nèi)存泄露就是指一個不再被程序使用的對象或變量一直被占據(jù)在內(nèi)存中估盘。java 中有垃

圾回收機制,它可以保證一對象不再被引用的時候骡尽,即對象編程了孤兒的時候遣妥,對象將自動

被垃圾回收器從內(nèi)存中清除掉。由于 Java 使用有向圖的方式進行垃圾回收管理攀细,可以消除

引用循環(huán)的問題箫踩,例如有兩個對象,相互引用谭贪,只要它們和根進程不可達的境钟,那么 GC 也是

可以回收它們的,例如下面的代碼可以看到這種情況的內(nèi)存回收:

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 中的內(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(elements.length == size){

Object[] oldElements = elements;

elements = new Object[2 * elements.length+1];

System.arraycopy(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{

s.push(new Object());

s.pop(); //這里有一個對象發(fā)生內(nèi)存泄露

s.push(new Object()); //上面的對象可以被回收了辅斟,等于是自愈了

}

}

因為是 static转晰,就一直存在到程序退出,但是我們也可以看到它有自愈功能士飒,就是說如

果你的 Stack 最多有100個對象查邢,那么最多也就只有100個對象無法被回收其實這個應(yīng)該很

容易理解,Stack 內(nèi)部持有100個引用变汪,最壞的情況就是他們都是無用的侠坎,因為我們一旦放

新的進取,以前的引用自然消失裙盾!

內(nèi)存泄露的另外一種情況:當一個對象被存儲進 HashSet 集合中以后实胸,就不能修改這個對

象中的那些參與計算哈希值的字段了,否則番官,對象修改后的哈希值與最初存儲進 HashSet

集合中時的哈希值就不同了庐完,在這種情況下,即使在 contains 方法使用該對象的當前引用

作為的參數(shù)去 HashSet 集合中檢索對象徘熔,也將返回找不到對象的結(jié)果门躯,這也會導致無法從

HashSet 集合中單獨刪除當前對象,造成內(nèi)存泄露酷师。

82讶凉、能不能自己寫個類,也叫 java.lang.String山孔?

可以懂讯,但在應(yīng)用的時候,需要用自己的類加載器去加載台颠,否則褐望,系統(tǒng)的類加載器永遠只是去

加載 jre.jar 包中的那個 java.lang.String。由于在 tomcat 的 web 應(yīng)用程序中串前,都是由 webapp

自己的類加載器先自己加載 WEB-INF/classess 目錄中的類瘫里,然后才委托上級的類加載器加

載,如果我們在 tomcat 的 web 應(yīng)用程序中寫一個 java.lang.String荡碾,這時候 Servlet 程序加

載的就是我們自己寫的 java.lang.String谨读,但是這么干就會出很多潛在的問題,原來所有用

了 java.lang.String 類的都將出現(xiàn)問題坛吁。

雖然 java 提供了 endorsed 技術(shù)劳殖,可以覆蓋 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 必須以分號結(jié)尾戳葵,且不帶花括號。

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(實現(xiàn))具體細節(jié)的,怎么可以用 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;

}

和上面的很相似携冤,都是關(guān)于 final 的問題悼粮,這有錯嗎?

答案: 正確。在 addOne method 中曾棕,參數(shù) 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 (構(gòu)造器)結(jié)束之前被賦予一個明確的值薯酝“牍粒可

以修改為"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();

}

}

答案:錯誤篇梭。在編譯時會發(fā)生錯誤(錯誤描述不同的 JVM 有不同的信息,意思就是未明確的

x 調(diào)用酝枢,兩個 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());

}

}

這個錯誤不容易發(fā)現(xiàn)袍患。

答案: 錯坦康。"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 文件復(fù)制到 d:\jad 目錄下识啦,并

將原來文件的擴展名從.java 改為.jad负蚊。

(大家正在做上面這道題,網(wǎng)上遲到的朋友也請做做這道題颓哮,找工作必須能編寫這些簡單問

題的代碼<易薄)

答:listFiles 方法接受一個 FileFilter 對象,這個 FileFilter 對象就是過慮的策略對象冕茅,不

同的人提供不同的 FileFilter 實現(xiàn)伤极,即提供了不同的過濾策略。

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);

}

}

}

由本題總結(jié)的思想及策略模式的解析:

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.將每個文件復(fù)制到另外一個目錄姨伤,并改擴展名

2.1 得到目標目錄哨坪,如果目標目錄不存在,則創(chuàng)建之

2.2 根據(jù)源文件名得到目標文件名姜挺,注意要用正則表達式齿税,注意.的轉(zhuǎn)義。

2.3 根據(jù)表示目錄的File和目標文件名的字符串炊豪,得到表示目標文件的File凌箕。

//要在硬盤中準確地創(chuàng)建出一個文件拧篮,需要知道文件名和文件的目

錄。

2.4 將源文件的流拷貝成目標文件流牵舱,拷貝方法獨立成為一個方法串绩,方法的

參數(shù)采用抽象流的形式。

//方法接受的參數(shù)類型盡量面向父類芜壁,越抽象越好礁凡,這樣適應(yīng)面更

寬廣。

}

分析 listFiles 方法內(nèi)部的策略模式實現(xiàn)原理

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慧妄、編寫一個截取字符串的函數(shù)顷牌,輸入為一個字符串和字節(jié)數(shù),輸出為按字節(jié)截

取的字符串塞淹,但要保證漢字不被截取半個窟蓝,如“我 ABC”,4饱普,應(yīng)該截取“我 AB”运挫,

輸入“我 ABC 漢 DEF”,6套耕,應(yīng)該輸出“我 ABC”谁帕,而不是“我 ABC+漢的半個”。

答:

首先要了解中文字符有多種編碼及各種編碼的特征冯袍。

假設(shè) n 為要截取的字節(jié)數(shù)匈挖。

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、有一個字符串康愤,其中包含中文字符关划、英文字符和數(shù)字字符,請統(tǒng)計和打印出

各個字符的個數(shù)翘瓮。

答:哈哈贮折,其實包含中文字符、英文字符资盅、數(shù)字字符原來是出題者放的煙霧彈调榄。

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"要分別統(tǒng)計英文字符的數(shù)量呵扛,中文字符的數(shù)量每庆,和數(shù)字

字符的數(shù)量,假設(shè)字符中沒有中文字符今穿、英文字符缤灵、數(shù)字字符之外的其他特殊字符。

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 實現(xiàn)二叉樹

這是組合設(shè)計模式帖鸦。

我有很多個(假設(shè)10萬個)數(shù)據(jù)要保存起來,以后還需要從保存的這些數(shù)據(jù)中檢索是否存在某

個數(shù)據(jù)胚嘲,(我想說出二叉樹的好處作儿,該怎么說呢?那就是說別人的缺點)馋劈,假如存在數(shù)組中攻锰,

那么,碰巧要找的數(shù)字位于99999那個地方妓雾,那查找的速度將很慢娶吞,因為要從第1個依次往

后取,取出來后進行比較械姻。平衡二叉樹(構(gòu)建平衡二叉樹需要先排序寝志,我們這里就不作考慮

了)可以很好地解決這個問題,但二叉樹的遍歷(前序策添,中序,后序)效率要比數(shù)組低很多毫缆,

原理如下圖:

代碼如下:

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唯竹、從類似如下的文本文件中讀取出所有的姓名,并打印出重復(fù)的姓名和重復(fù)的

次數(shù)苦丁,并按重復(fù)次數(shù)排序:

1,張三,28

2,李四,35

3,張三,28

4,王五,35

5,張三,28

6,李四,35

7,趙六,28

8,田七,35

程序代碼如下(答題要博得用人單位的喜歡浸颓,包名用該公司,面試前就提前查好該公司的網(wǎng)

址旺拉,如果查不到产上,現(xiàn)場問也是可以的。還要加上實現(xiàn)思路的注釋):

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

//下面的代碼沒有執(zhí)行沉桌,說明往 treeset 中增加數(shù)據(jù)時谢鹊,不會使用到 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 返回結(jié)果0留凭,則認為兩個對象相等佃扼,新的對象不

會增加到集合中去

* 所以,不能直接用下面的代碼蔼夜,否則兼耀,那些個數(shù)相同的其他姓名

就打印不出來。

* */

//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);

}

}?

}

}

注:出自牛客網(wǎng)-程序員筆試面試題庫瘤运,程序員求職備考網(wǎng)站 http://www.nowcoder.com”窍霞,學習分享,侵刪>〕9俸场!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末似谁,一起剝皮案震驚了整個濱河市傲绣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌巩踏,老刑警劉巖秃诵,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異塞琼,居然都是意外死亡菠净,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門彪杉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毅往,“玉大人,你說我怎么就攤上這事派近∨饰ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵渴丸,是天一觀的道長侯嘀。 經(jīng)常有香客問我,道長谱轨,這世上最難降的妖魔是什么戒幔? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮土童,結(jié)果婚禮上诗茎,老公的妹妹穿的比我還像新娘。我一直安慰自己献汗,他們只是感情好错沃,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著雀瓢,像睡著了一般枢析。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刃麸,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天醒叁,我揣著相機與錄音,去河邊找鬼。 笑死把沼,一個胖子當著我的面吹牛啊易,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播饮睬,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼租谈,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了捆愁?” 一聲冷哼從身側(cè)響起割去,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昼丑,沒想到半個月后呻逆,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡菩帝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年咖城,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呼奢。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡宜雀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出握础,到底是詐尸還是另有隱情辐董,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布弓候,位于F島的核電站,受9級特大地震影響他匪,放射性物質(zhì)發(fā)生泄漏菇存。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一邦蜜、第九天 我趴在偏房一處隱蔽的房頂上張望依鸥。 院中可真熱鬧,春花似錦悼沈、人聲如沸贱迟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衣吠。三九已至,卻和暖如春壤靶,著一層夾襖步出監(jiān)牢的瞬間缚俏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留忧换,地道東北人恬惯。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像亚茬,于是被迫代替她去往敵國和親酪耳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350