1. 程式人生 > >java提高篇——基礎查缺補漏(面試)

java提高篇——基礎查缺補漏(面試)

連結:http://blog.csdn.net/xiaokang123456kao/article/details/54233595

連結失效請複製改連結至位址列


一.java基本資料型別所佔的記憶體大小

在Java中一共有8種基本資料型別,其中有4種整型,2種浮點型別,1種用於表示Unicode編碼的字元
單元的字元型別和1種用於表示真值的boolean型別。(一個位元組等於8個bit)
1.整型
型別              儲存需求     bit數    取值範圍                備註
int                  4位元組          4*8 
short             2位元組          2*8    -32768~32767
long              8位元組          8*8
byte              1位元組           1*8    -128~127
2.浮點型
型別              儲存需求     bit數    取值範圍      備註
float              4位元組           4*8                             float型別的數值有一個字尾F(例 如:3.14F)
double          8位元組          8*8                             沒有後綴F的浮點數值(如3.14)預設為double型別
3.char型別
型別              儲存需求     bit數     取值範圍      備註
char              2位元組           2*8
4.boolean型別
型別              儲存需求    bit數    取值範圍      備註
boolean        1位元組          1*8      false、true
補充:Java有一個能夠表示任意精度的算書包,通常稱為“大數值”(big number)。雖然被稱為大
數值,但它並不是一種Java型別,而是一個Java物件。
如果基本的整數和浮點數精度不能夠滿足需求,那麼可以使用java.math包中的兩個很有用的類:
BigIntegerBigDecimal(Android SDK中也包含了java.math包以及這兩個類)這兩個類可以處理包含
任意長度數字序列的數值。BigInteger類實現了任意精度的整數運算,BigDecimal實現了任意精度

的浮點數運算。


二、關於漢字在java中儲存所佔的位元組大小(待調查)

java中的char型別是使用UTF16來編碼的,也就是說用16位(也就是兩位元組)來表示一個char,一個漢字需要兩位元組來儲存,所以,一個char剛好可以存下一個漢字。Java一律採用Unicode編碼方式,每個字元無論中文還是英文字元都佔用2個位元組。實際情況下:一個英文字母(不分大小寫)佔兩個位元組的空間,但其中一個位元組未被使用。一箇中文漢字佔兩個位元組的空間。英文標點佔兩個位元組,中文標點佔兩個位元組.用char來存一個英文字母時,有一半的儲存空間浪費了,兩個位元組只利用了一個位元組的空間。注意:不同的編碼格式佔位元組數是不同的。UTF-8編碼下一個中文所佔位元組也是不確定的,可能是2個、3個、4個位元組。

字串“學java”在java預設編碼下所佔位元組數為10,每個字元佔兩個位元組。不過,其中“java”佔用的8個位元組中有4個位元組為空。

實現國際化應用常用的手段是利用ResourceBundle類。ResourceBundle能夠依據Local的不同,選擇性的讀取與Local對應字尾的properties檔案,以達到國際化的目的。

三、抽象類和介面

抽象類:
用abstract修飾,抽象類中可以沒有抽象方法,但有抽象方法的類一定是抽象類,且抽象方法定義時不能有方法體;抽象類不可以例項化只能通過繼承在子類中實現其所有的抽象方法;抽象類如果不被繼承就沒有任何意義;抽象類為子類定義了一個公共型別,封裝了子類中的重複內容。
介面:

用Interface關鍵字定義介面;是特殊的抽象類,因為類中只包含抽象方法;介面中不能定義成員變數可以定義常量;介面是其通過其他類使用implements關鍵字定義實現類,一個類一旦實現介面就必須實現其中的所有抽象方法;一個類可以實現多個介面,介面名之間用逗號隔開即可;一個介面可以通過extends關鍵字繼承另一個介面,與此同時繼承了父類中的所有方法。

四、java.lang包中不能被繼承的類
public final class Character
public static final class Character.UnicodeBlock
public final class Class<T>
public final class Compile


public final class Byte
public final class Double
public final class Float
public final class Integer
public final class Short
public final class Long
public final class Math


public final class String
public final class StrictMath
public final class StringBuffer
public final class StringBuilder
public final class ProcessBuilder


public final class RuntimePermission
public final class StackTraceElement


public final class System
public final class Void

五、靜態塊和構造塊
普通程式碼塊:在方法或語句中出現的{}就稱為普通程式碼塊。普通程式碼塊和一般的語句執行順序由他們在程式碼中出現的次序決定--“先出現先執行”。
構造塊:直接在類中用{}定義的而不是出現在類的方法中,且沒有加static關鍵字的程式碼塊稱為構造程式碼塊。構造程式碼塊在建立物件時被呼叫,每次建立物件都會被呼叫,並且構造程式碼塊的執行次序優先於類建構函式。
靜態程式碼塊:在java中使用static關鍵字宣告的程式碼塊。靜態塊用於初始化類,為類的屬性初始化。每個靜態程式碼塊只會執行一次。由於JVM在載入類時會執行靜態程式碼塊,所以靜態程式碼塊先於主方法(即main方法)執行。如果類中包含多個靜態程式碼塊,那麼將按照"先定義的程式碼先執行,後定義的程式碼後執行"。
注意:1、靜態程式碼塊不能存在於任何方法體內。2、靜態程式碼塊不能直接訪問靜態例項變數和例項方法,需要通過類的例項物件來訪問。
執行順序:(優先順序從高到低。)靜態程式碼塊>main方法>構造程式碼塊>構造方法。
其中靜態程式碼塊只執行一次。構造程式碼塊在每次建立物件是都會執行。

[java]  view plain  copy
  1. <span style="font-size:24px;">class Code{  
  2.     {  
  3.       System.out.println("Code的構造塊");  
  4.     }  
  5.       
  6.     static{  
  7.         System.out.println("Code的靜態程式碼塊");  
  8.         }  
  9.           
  10.     public Code(){  
  11.         System.out.println("Code的構造方法");  
  12.         }  
  13.     }  
  14.       
  15.       
  16. public class CodeBlock03{  
  17.      {  
  18.       System.out.println("CodeBlock03的構造塊");      
  19.      }  
  20.        
  21.      static{  
  22.         System.out.println("CodeBlock03的靜態程式碼塊");  
  23.         }  
  24.           
  25.         public CodeBlock03(){  
  26.              System.out.println("CodeBlock03的構造方法");  
  27.             }  
  28.           
  29.       public static void main(String[] args){  
  30.             System.out.println("CodeBlock03的主方法");  
  31.             new Code();  
  32.             new Code();  
  33.             new CodeBlock03();  
  34.             new CodeBlock03();  
  35.           }  
  36.     }  
  37. /* 
  38. CodeBlock03的靜態程式碼塊 
  39. CodeBlock03的主方法 
  40. Code的靜態程式碼塊 
  41. Code的構造塊 
  42. Code的構造方法 
  43. Code的構造塊 
  44. Code的構造方法 
  45. CodeBlock03的構造塊 
  46. CodeBlock03的構造方法 
  47. CodeBlock03的構造塊 
  48. CodeBlock03的構造方法 
  49. */</span>  


[java]  view plain  copy
  1. <span style="font-size:24px;">public class B  
  2. {  
  3.     public static B t1 = new B();  
  4.     public static B t2 = new B();  
  5.     {  
  6.         System.out.println("構造塊");  
  7.     }  
  8.     static  
  9.     {  
  10.         System.out.println("靜態塊");  
  11.     }  
  12.     public static void main(String[] args)  
  13.     {  
  14.         B t = new B();  
  15.     }  
  16. }</span>  
上述程式碼執行結果:

構造塊  //首先執行public static B t1 = new B();這個靜態程式碼塊,new呼叫了構造塊

構造塊 //再執行public static B t2 = new B();這個靜態程式碼塊,new呼叫了構造塊

靜態塊 //然後執行static{System.out.println("靜態");}這個靜態程式碼塊

構造塊//最後執行main方法,main方法中的B t = new B();語句執行時,首先執行構造程式碼塊,再執行對應的建構函式。


六、==和equal()

在Java中游8種基本資料型別:
浮點型:float(4 byte), double(8 byte)
整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
字元型: char(2 byte)
布林型: boolean(JVM規範沒有明確規定其所佔的空間大小,僅規定其只能夠取字面值"true"和"false")
對於這8種基本資料型別的變數,變數直接儲存的是“值”,因此在用關係操作符==來進行比較時,比較的就是 “值” 本身。
而對於非基本資料型別的變數,即引用型別的變數。引用型別的變數儲存的並不是 “值”本身,而是於其關聯的物件在記憶體中的地址。
對於==,如果作用於基本資料型別的變數,則直接比較其儲存的 “值”是否相等;如果作用於引用型別的變數,則比較的是所指向的物件的地址是否相同。
對於equals方法,注意:equals方法不能作用於基本資料型別的變數。如果沒有對equals方法進行重寫,則比較的是引用型別的變數所指向的物件的地址;String類對equals方法進行了重寫,用來比較指向的字串物件所儲存的字串是否相等。諸如String、Date等類對equals方法進行了重寫的話,比較的是所指向的物件的內容。

七、java的拆箱和裝箱

什麼是自動裝箱拆箱

基本資料型別的自動裝箱(autoboxing)、拆箱(unboxing)是自J2SE 5.0開始提供的功能。

一般我們要建立一個類的物件例項的時候,我們會這樣:

Class a= new Class(parameter);

當我們建立一個Integer物件時,卻可以這樣:

Integeri = 100; (注意:不是 int i = 100; )

實際上,執行上面那句程式碼的時候,系統為我們執行了:Integer i = Integer.valueOf(100);

此即基本資料型別的自動裝箱功能。

 

基本資料型別與物件的差別

基本資料型別不是物件,也就是使用int、double、boolean等定義的變數、常量。

基本資料型別沒有可呼叫的方法。

eg:  int t = 1;     t.  後面是沒有方法

Integer t =1; t.  後面就有很多方法可讓你呼叫了。

 

什麼時候自動裝箱

例如:Integer i = 100;

相當於編譯器自動為您作以下的語法編譯:Integer i = Integer.valueOf(100);

 

什麼時候自動拆箱

自動拆箱(unboxing),也就是將物件中的基本資料從物件中自動取出。如下可實現自動拆箱:

Integer i = 10; //裝箱

int t = i; //拆箱,實際上執行了 int t =i.intValue();

在進行運算時,也可以進行拆箱。

Integer i = 10;

System.out.println(i++);

 

Integer的自動裝箱

在-128~127 之外的數

Integer i1 =200;  

Integer i2 =200;          

System.out.println("i1==i2:"+(i1==i2));       

輸出的結果是:

i1==i2: false

 

在-128~127 之內的數

Integer i3 =100; 

Integer i4 =100;  

System.out.println("i3==i4:"+(i3==i4));

輸出的結果是: 

i3==i4: true

 

 

 

java中Integer.valueOf的原始碼

public static Integer valueOf(int i) {

   if(i >= -128 && i <= IntegerCache.high)  // 沒有設定的話,IngegerCache.high預設是127

       return IntegerCache.cache[i + 128];

   else

       return new Integer(i);

}

對於–128到127(預設是127)之間的值,Integer.valueOf(int i) 返回的是快取的Integer物件(並不是新建物件)

所以範例中,i3 與 i4實際上是指向同一個物件。

而其他值,執行Integer.valueOf(int i) 返回的是一個新建的 Integer物件,所以範例中,i1與i2 指向的是不同的物件。

當然,當不使用自動裝箱功能的時候,情況與普通類物件一樣,請看下例:

Integer i3 =new Integer(100);

Integer i4 =new Integer(100);

System.out.println("i3==i4:"+(i3==i4));//顯示false

 

String 的拆箱裝箱

 

先看個例子:

String str1 ="abc";

String str2 ="abc";

System.out.println(str2==str1); //輸出為 true

System.out.println(str2.equals(str1)); //輸出為 true

 

String str3 =new String("abc");

String str4 =new String("abc");

System.out.println(str3==str4); //輸出為 false

System.out.println(str3.equals(str4)); //輸出為 true

str3與str4也是各自new了個物件,而str1與str2卻是引用了同一個物件。


Integer i01=59;
int i02=59;
Integer i03=Integer.valueOf(59);
Integer i04=new Integer(59);

i01==i02//true(先拆箱,再比較。所以i02==i03,i02==i04都是true)

i01=i03//true(59在-128-127之間,所以返回的是快取區中的同一個Integer物件)

i04是新建的物件,所以i04==i01,i04==i03都是false


八、jsp的物件和域

Jsp九大內建物件和四種作用域

1.request

 request物件是javax.servlet.httpServletRequest型別的物件。該物件代表了客戶端的請求資訊,主要用於接受通過HTTP協議傳送到伺服器的資料。(包括頭資訊、系統資訊、請求方式以及請求引數等)。通俗來講就是客戶端的請求資訊被封裝在Request物件中,並傳給伺服器。

2.response

 response代表的是對客戶端的響應,主要是將JSP容器處理過的物件傳回到客戶端。但在JSP頁面中很少直接用到。

3.session

  從客戶端到伺服器的一次會話,從一個客戶開啟瀏覽器並連線到伺服器開始,直到客戶端與伺服器斷開連線為止。

4.application

 application伺服器啟動後就產生application物件,直到伺服器結束。實現了使用者間資料的共享,可存放全域性變數。與session不同的是,所有客戶的application物件都是同一個,在任何地方對此物件屬性的操作,都將影響到其他使用者對此的訪問。它是ServletContext類的例項。

5.out

   用於在WEB瀏覽器內輸出資訊,並且管理應用伺服器上的輸出緩衝區。

6.page

   代表JSP本身,只有在JSP頁面內才是合法的。類似於Java程式設計中的this指標。

7.config

   主要作用是取的伺服器的配置資訊。通過 pageContext物件的 getServletConfig() 方法可以獲取一個config物件。當一個Servlet 初始化時,容器把某些資訊通過 config物件傳遞給這個 Servlet。開發者可以在web.xml 檔案中為應用程式環境中的Servlet程式和JSP頁面提供初始化引數。

8.exception

   Java.lang.Throwable的例項。當一個頁面在執行過程中發生了例外,就產生這個物件。如果一個JSP頁面要應用此物件,就必須把isErrorPage設為true,否則無法編譯。

9.pageContext

   pageContext物件的作用是獲取任何範圍的引數,通過它可以獲取JSP頁面的out、request、response、session、application等物件。pageContext物件的建立和初始化都是由容器來完成,在JSP頁面中可以直接使用 pageContext物件。

四種作用域:

 page-> 頁面級別,顯然只有在一個頁面內可用。

 request -> 請求級別 伺服器跳轉,一次請求之後消失。

 session -> 會話級別 客戶端跳轉(伺服器跳轉),與瀏覽器有關,ie是在重新開啟ie時才會不同。

 application = 應用級別,當重啟伺服器時才會消失

九、java I/O流的層次關係



十、java集合類的特點與區別

java集合類層次關係:

Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap

1.有序/無序和重複元素

 型別

有序否

允許元素重複否

能否存NULL

List

Set

AbstractSet

最多有一個null元素

HashSet

TreeSet

是(用二叉樹排序)

Map

AbstractMap

使用key-value來對映和儲存資料,

Key必須惟一,value可以重複

 

 允許null,即null value

null key

HashMap

TreeMap

是(用二叉樹排序)

2.hashtable與hashmap區別

① HashMap可以儲存null鍵值對,Hashtable不能儲存null鍵值對;
② HashMap是非synchronized,而Hashtable是synchronized。sychronized意味著在一次僅有一個執行緒能夠更改Hashtable。就是說任何執行緒要更新Hashtable時要首先獲得同步鎖,其它執行緒要等到同步鎖被放之後才能再次獲得同步鎖更新Hashtable。也就是說,Hashtable是執行緒安全的,多個執行緒可以共享一個Hashtable;而如果沒有正確的同步的話,多個執行緒是不能共享HashMap的。由於Hashtable是執行緒安全的也是synchronized,所以在單執行緒環境下它比HashMap要慢。如果不需要同步只需要單一執行緒,那麼使用HashMap效能要好過Hashtable。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的擴充套件性更好。所以如果需要完全安全的執行緒,需要使用Hashtable或者ConcurrentHashMap。

3.List、vector、set、map的區別與聯絡

Vector : 基於Array的List,其實就是封裝了Array所不具備的一些功能方便我們使用,它不可能走出Array的限制。效能也就不可能超越Array。所以,在可能的情況下,我們要多運用Array。另外很重要的一點就是Vector“sychronized”的,這個也是Vector和ArrayList的唯一的區別。
ArrayList:同Vector一樣是一個基於Array上的連結串列,但是不同的是ArrayList不是同步的。所以在效能上要比Vector優越一些,但是當執行到多執行緒環境中時,可需要自己在管理執行緒的同步問題。
LinkedList:LinkedList不同於前面兩種List,它不是基於Array的,所以不受Array效能的限制。它每一個節點(Node)都包含兩方面的內容:1.節點本身的資料(data);2.下一個節點的資訊(nextNode)。所以當對LinkedList做新增,刪除動作的時候就不用像基於Array的List一樣,必須進行大量的資料移動。只要更改nextNode的相關資訊就可以實現了。這就是LinkedList的優勢。
總結:基於Array的List(Vector,ArrayList)適合查詢,而LinkedList(連結串列)適合新增,刪除操作。


set:雖然Set同List都實現了Collection介面,但是他們的實現方式卻大不一樣。List基本上都是以Array為基礎。但是Set則是在HashMap的基礎上來實現的,這個就是Set和List的根本區別。

HashSet:HashSet的儲存方式是把HashMap中的Key作為Set的對應儲存項。Set中不能像在List中一樣有重複的項的根本原因,因為HashMap的key是不能有重複的。

LinkedHashSet:HashSet的一個子類,一個連結串列。
TreeSet:SortedSet的子類,它不同於HashSet的根本就是TreeSet是有序的。它是通過SortedMap來實現的。


4、如何選擇?
(1)容器類和Array的區別、擇取
* 容器類僅能持有物件引用(指向物件的指標),而不是將物件資訊copy一份至數列某位置。
* 一旦將物件置入容器內,便損失了該物件的型別資訊。


(2)
* 在各種Lists中,最好的做法是以ArrayList作為預設選擇。當插入、刪除頻繁時,使用LinkedList();
Vector總是比ArrayList慢,所以要儘量避免使用。
* 在各種Sets中,HashSet通常優於HashTree(插入、查詢)。只有當需要產生一個經過排序的序列,才用TreeSet。
HashTree存在的唯一理由:能夠維護其內元素的排序狀態。 
* 在各種Maps中
HashMap用於快速查詢。
* 當元素個數固定,用Array,因為Array效率是最高的。

結論:最常用的是ArrayList,HashSet,HashMap,Array。


5、注意

Collection沒有get()方法來取得某個元素。只能通過iterator()遍歷元素。

List,可以通過get()方法來一次取出一個元素。使用數字來選擇一堆物件中的一個,get(0)...。(add/get)

集合中執行緒安全的類有:vector,stack,hashtable,enumeration,除此之外均是非執行緒安全的類與介面。