1. 程式人生 > >Android/Java面試題,邊面試邊成長,為了應試而應試

Android/Java面試題,邊面試邊成長,為了應試而應試

從今天起,所有面試或遇到過的面試題,都整理到此文章下,提醒自己時刻要學習,同時分享給各位。【部分網上整理】

Java基礎

    1,Java中一個漢字佔多少位元組?

java中,只要是字元,不管是數字還是英文還是漢字,都佔兩個位元組,都是一個char。
char c1 = ‘中’; char c2 = ‘A’; char c3 = ‘1’;
確切說,Unicode編碼是指一類編碼的統稱,而非某個具體編碼。
在java中字元,即char是用unicode編碼的,而字串,即String在java中是通過char[]的形式實現的,所以也是unicode編碼的。
漢字在java中是字串,用unicode編碼,unicode佔兩個位元組。

    2,集合的實現類與區別?

Collection介面,集合結構總的父介面,有兩個子介面list和set
List介面 元素有序可重複.
實現類有:
ArrayList 陣列實現輕量級,執行快,執行緒不安全。JDK1.2 查詢快
Vector 陣列實現重量級,執行慢,執行緒安全。JDK1.0
LinkedList連結串列實現 常用語堆疊與佇列的實現 增刪操作快
Set 介面 元素無序不可重複
實現類有:
HashSet,底層用hashCode()演算法實現,保證元素的無序唯一,自定義物件存進HashSet為了保證元素內容不重複需要覆蓋hashCode()與equals()方法。
SortedSet(不重要) 元素有序(Unicode升序)唯一
TreeSet要求元素有序,自定義的物件需要實現Comparable介面的compareTo(object o)方法
Map(介面): 與Collection介面無關

,有一個子介面SortedMap特點: 元素是key-value,key唯一,無序; value可重複
實現類:
HashMap 輕量級 執行緒不安全的,允許key或value為null JDK1.2
HashTable 重量級 執行緒安全的 不允許key或value為null JDK1.0(Properties是HashTable的子類,主鍵和值都是字串)
SortedMap:(不重要)特點: key唯一,有序(Unicode升序) 實現類:TreeMap

    3,方法過載與覆蓋的區別?( Overload與Override的區別)

方法的過載屬於編譯時多型,方法名相同引數列表不同,返回值必須相同或都沒有返回值型別。方法的覆蓋屬於執行時多型,子類覆蓋父類的方法,子類指向父類引用,在呼叫方法的時候用父類的引用呼叫。

    4,String和StringBuffer的區別

String的長度是不可變的,StringBuffer的長度是可變的。如果你對字串中的內容經常進行操作,特別是內容要修改時,那麼使用StringBuffer,如果最後需要String,那麼使用StringBuffer的toString()方法,StringBuder是不安全的 String 是安全的。

    5,字串“abcde”通過寫一個函式不讓呼叫第三方的字串,實現一個字串倒序,比如字串“abcde”變成“edcba”

String src = “ABCDEF “;
String dst = new StringBuffer(src).reverse().toString();

    6,抽象類與介面的區別(abstract與interface的區別)

abstract可以修飾抽象方法,而一個類只要有一個抽象方法,就必須用abstract定義該類,即抽象類。
用interface修飾的類,裡面的方法都是抽象方法,因此在定義介面的時候,可以直接不加那些修飾,系統會預設的添上去。接口裡面的欄位都是公有常量,即public static final修飾的欄位。

    7、執行緒有幾種狀態,分別是哪些?(呼叫run()和呼叫start()的區別)

1)、新建狀態(New):新建立了一個執行緒物件。
2)、就緒狀態(Runnable):執行緒物件建立後,其他執行緒呼叫了該物件的start()方法。該狀態的執行緒位於可執行執行緒池中,變得可執行,等待獲取CPU的使用權。
3)、執行狀態(Running):就緒狀態的執行緒獲取了CPU,執行run()方法。
4)、阻塞狀態(Blocked):阻塞狀態是執行緒因為某種原因放棄CPU使用權,暫時停止執行。直到執行緒進入就緒狀態,才有機會轉到執行狀態。阻塞的情況分三種:
  (一)、等待阻塞:執行的執行緒執行wait()方法,JVM會把該執行緒放入等待池中。
  (二)、同步阻塞:執行的執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒佔用,則JVM會把該執行緒放入鎖池中。
  (三)、其他阻塞:執行的執行緒執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該執行緒置為阻塞狀態。當sleep()狀態超時、join()等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入就緒狀態。
5)、死亡狀態(Dead):執行緒執行完了或者因異常退出了run()方法,該執行緒結束生命週期。
當呼叫start方法的時候,該執行緒就進入就緒狀態。等待CPU進行排程執行,此時還沒有真正執行執行緒。
當呼叫run方法的時候,是已經被CPU進行排程,執行執行緒的主要任務。

    8、sleep()與 wait()的區別

1.這兩個方法來自不同的類分別是,sleep來自Thread類,和wait來自Object類。
2.最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其他執行緒可以使用同步控制塊或者方法。sleep不出讓系統資源;wait是進入執行緒等待池等待,出讓系統資源,其他執行緒可以佔用CPU。一般wait不會加時間限制,因為如果wait執行緒的執行資源不夠,再出來也沒用,要等待其他執行緒呼叫notify/notifyAll喚醒等待池中的所有執行緒,才會進入就緒佇列等待OS分配系統資源。sleep(milliseconds)可以用時間指定使它自動喚醒過來,如果時間不到只能呼叫interrupt()強行打斷。
3.wait,notify和notifyAll只能在同步控制方法或者同步控制塊裡面使用,而sleep可以在任何地方使用
4. Sleep需要捕獲異常,而wait不需要

    9,執行緒中wait,join,sleep,yield, notify,notifyall,synchronized,區別及聯絡

1).sleep()
在指定時間內讓當前正在執行的執行緒暫停執行,但不會釋放“鎖標誌”。不推薦使用。sleep()使當前執行緒進入阻塞狀態,在指定時間內不會執行。
2).wait()
在其他執行緒呼叫物件的notify或notifyAll方法前,導致當前執行緒等待。執行緒會釋放掉它所佔有的“鎖標誌”,從而使別的執行緒有機會搶佔該鎖。
喚醒當前物件鎖的等待執行緒使用notify或notifyAll方法,waite() 和notify()必須在synchronized函式或synchronized block中進行呼叫。
yield方法暫停當前正在執行的執行緒物件。yield()只是使當前執行緒重新回到可執行狀態,所以執行
3).yield()
的執行緒有可能在進入到可執行狀態後馬上又被執行。yield()只能使同優先順序或更高優先順序的執行緒有執行的機會。
4).join()
等待該執行緒終止。等待呼叫join方法的執行緒結束,再繼續執行。如:t.join();//主要用於等待t執行緒執行結束,若無此句,main則會執行完畢,導致結果不可預測。

    10,Final、finally、finanlize()的區別

final用於宣告屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會呼叫被回收物件的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉檔案等。
Loader: 裝載器從android3.0開始引進。它使得在activity或fragment中非同步載入資料變得簡單。

    11、一個".java"原始檔中是否可以包括多個類(不是內部類)?有什麼限制?

可以有多個類,但只能有一個public的類,並且public的類名必須與檔名相一致。

    12、Java有沒有goto?

java中的保留字,現在沒有在java中使用。

    13、說說&和&&的區別。

&和&&都可以用作邏輯與的運算子,表示邏輯與(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。

    14、在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.length; j++) {
                System.out.println("i=" + i + ",j=" + j);
                if (arr[i][j] == 5) {
                    found = true;
                    break;
                }
            }
        }
    15、switch語句能否作用在byte上,能否作用在long上,能否作用在String上?

在switch(expr1)中,expr1只能是一個整數表示式或者列舉常量(更大字型),整數表示式可以是int基本型別或Integer包裝型別,由於,byte,short,char都可以隱含轉換為int,所以,這些型別以及這些型別的包裝型別也是可以的。顯然,long和String型別都不符合switch的語法規定,並且不能被隱式轉換成int型別,所以,它們不能作用於swtich語句中。

    16、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編譯器會對它進行特殊處理,因此可以正確編譯。

    17、char型變數中能不能存貯一箇中文漢字?為什麼?

char型變數是用來儲存Unicode編碼的字元的,unicode編碼字符集中包含了漢字,所以,char型變數中當然可以儲存漢字啦。不過,如果某個特殊的漢字沒有被包含在unicode編碼字符集中,那麼,這個char型變數中就不能儲存這個特殊漢字。補充說明:unicode編碼佔用兩個位元組,所以,char型別的變數也是佔用兩個位元組。

    18、用最有效率的方法算出2乘以8等於幾?

2 << 3,
因為將一個數左移n位,就相當於乘以了2的n次方,那麼,一個數乘以8只要將其左移3位即可,而位運算cpu直接支援的,效率最高,所以,2乘以8等於幾的最效率的方法是2<< 3。

Android部分

    瀑布流是怎麼實現的

其實瀑布流的大體佈局是由一個ScrollView和LinearLayout組成,LinearLayout包裹在ScrollView中,而其中的每一列也是一個LinearLayout佈局,內部為垂直分佈,根據要求來顯示分為n列,通過要求的列數來判斷建立n個LinearLayout佈局,而每個列的寬度是整個螢幕寬度的1/n,高度為鋪滿全屏,通過將請求來的圖片進行每組n個的依次迴圈往n列中各個填充。

    側滑是怎麼實現的

首先還是講一下實現原理。在一個Activity的佈局中需要有兩部分,一個是選單(menu)的佈局,一個是內容(content)的佈局。兩個佈局橫向排列,選單佈局在左,內容佈局在右。初始化的時候將選單佈局向左偏移,以至於能夠完全隱藏,這樣內容佈局就會完全顯示在Activity中。然後通過監聽手指滑動事件,來改變選單佈局的左偏移距離,從而控制選單佈局的顯示和隱藏。

    你對快取的理解,為什麼要進行快取

客戶端快取機制是android應用開發中非常重要的一項工作,使用快取機制不僅僅可以為使用者節省3G流量,同時在使用者體驗方面也是非常好的選擇.
快取機制分為兩部分,一部分是文字快取,另一部分是多媒體檔案快取.
快取的優點
1.伺服器的壓力大大減小
2. 客戶端的響應速度大大變快(使用者體驗)
3. 客戶端的資料加載出錯情況大大較少,大大提高了應有的穩定性(使用者體驗)
4. 一定程度上可以支援離線瀏覽(或者說為離線瀏覽提供了技術支援)

    Sqlite怎麼進行版本更新

通過SQLiteOpenHelper類中的onUpgrade方法來判斷比較版本號進行是否版本更新。

    Sqlite怎麼插入資料,插入一萬條資料怎麼操作

在執行SQL語句前開啟事務,在執行完後再關閉事務,例如:

        long starttime = System.currentTimeMillis();
        System.out.println(starttime + "");
        myDB.beginTransaction();
        for (int i = 0; i < 2000; i++) {
            myDB.execSQL("insert into meetings (id ,mainid) values ( '1','1')");
        }
        myDB.setTransactionSuccessful();
        myDB.endTransaction();
    如何自定義View?

自定義View其實就是繼承View,並實現onDraw(),OnMeasure(),OnLayout()方法。
1,如果需要改變View繪製的影象,那麼需要重寫OnDraw方法。(這也是最常用的重寫方式。)
2,如果需要改變view的大小,那麼需要重寫OnMeasure方法。
3,如果需要改變View的(在父控制元件的)位置,那麼需要重寫OnLayout方法。

    Arraylist和linkedlist有什麼區別,它們都是現成安全的嗎?

ArrayList陣列實現,輕量級(消耗系統資源少),執行快,執行緒不安全,JDK1.2;
LinkedList 連結串列實現 常用於堆疊與佇列的實現
注: 陣列元素連續順序存放,查詢快, 增刪慢 連結串列元素順序存放,查詢慢, 增刪快
都不是執行緒安全的。

    用沒用過事務,怎麼用

sqlite 是支援事務處理的。如果你知道你要同步刪除很多資料,不仿把它們做成一個統一的事務。通常一次 sqlite3_exec 就是一次事務,如果你要刪除1萬條資料,sqlite就做了1萬次:開始新事務->刪除一條資料->提交事務->開始新事務->… 的過程。這個操作是很慢的。因為時間都花在了開始事務、提交事務上。

—————-2015年4月23日更新—————-

    Android dvm的程序和Linux的程序, 應用程式的程序是否為同一個概念

Dalvik
Dalvik是Google公司自己設計用於Android平臺的Java虛擬機器。它可以支援已轉換為.dex(即Dalvik Executable)格式的Java應用程式的執行,.dex格式是專為Dalvik設計的一種壓縮格式,可以減少整體檔案尺寸,提高I/o操作的類查詢速度所以適合記憶體和處理器速度有限的系統。
暫存器
暫存器是中央處理器內的組成部分。暫存器是有限存貯容量的高速存貯部件,它們可用來暫存指令、資料和位址。在中央處理器的控制部件中,包含的暫存器有指令暫存器(IR)和程式計數器(PC),在中央處理器的算術及邏輯部件中,包含的暫存器有累加器(ACC)。

棧是執行緒獨有的,儲存其執行狀態和區域性自動變數的(所以多執行緒中區域性變數都是相互獨立的,不同於類變數)。棧線上程開始的時候初始化(執行緒的Start方法,初始化分配棧),每個執行緒的棧互相獨立。每個函式都有自己的棧,棧被用來在函式之間傳遞引數。作業系統在切換執行緒的時候會自動的切換棧,就是切換SS/ESP暫存器。棧空間不需要在高階語言裡面顯式的分配和釋放。

DVM程序的設計規則
1)每個應用程式都執行在它自己的Linux空間。在需要執行該應用程式時Android將啟動該程序,當不再需要該應用程式,並且系統資源分配不夠時,則系統終止該程序。
2)每個應用程式都有自己的(DVM),所以任一應用程式的程式碼與其他應用程式的程式碼是相互隔離的。
3)預設情況下,每個應用程式都給分配一個唯一的Linux使用者ID。所以應用程式的檔案只能對該應用程式可見。

所以說每個應用程式都擁有一個獨立的DVM,而每個DVM在Linux中又是一個程序,所以說DVM程序和Linux程序可以說是一個概念

DVM和JVM區別
首要的差別:Dalvik 基於暫存器,而JVM 基於棧。效能有很大的提升。基於暫存器的虛擬機器對於更大的程式來說,在它們編譯的時候,花費的時間更短。
執行的位元組碼不一樣,前者是dex格式,後者是.class格式。Dex是針對移動裝置進行了優化。

Android 應用程式的編譯
用jar解壓一個android應用apk,如下圖所示:
這裡寫圖片描述
Android所有類都通過JAVA編譯器編譯,然後通過Android SDK的“dex檔案轉換工具”轉換為“dex”的位元組檔案,再由DVM載入執行。
classes.dex 是java原始碼編譯後生成的java位元組碼檔案.但由於Android使用的dalvik虛擬機器與標準的java虛擬機器是不相容的,dex檔案與class檔案相比,不論是檔案結構還是opcode都不一樣。
想反編譯別人的應用,就可以用諸如dex2jar這樣的工具去還原classes.dex