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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章