關鍵字:html
1. final、finalize、finally對比java
(1)性質不一樣api
(2)做用不一樣數組
2. throws和throw對比 (Java中throws和throw的區別講解)安全
(1)使用位置不一樣多線程
(2)內容不一樣app
(3)做用不一樣jvm
總結:函數調用時,若是須要向上層拋出異常,就必須在函數頭部顯式地聲明(throws Exception1, Exception2)異常類型;若是僅須要在方法體內部處理異常,方法體內部可自行處理該異常,thorw拋出具體的異常實例(catch(Exception1 e){...})。函數
3. static關鍵字的做用性能
static關鍵字可用來修飾屬性、方法、代碼塊,目的是把對象相關的變成類相關的,即:不加static的成員是對象相關的,歸單個對象全部;加static修飾的成員是類成員,能夠經過類名直接調用,歸全部對象全部。
static修飾的成員變量和成員方法習慣上稱爲靜態變量和靜態方法,能夠直接經過類名來訪問,訪問語法爲:
(1)static修飾屬性(類變量、靜態變量)
因此通常在須要實現如下兩個功能時使用靜態變量:
1)在對象之間共享值時;2)方便訪問變量時
(2)static修飾方法(靜態方法)
Java中main方法必須爲static的緣由:
在類加載時沒法建立對象,而靜態方法能夠不經過對象調用,因此在類加載時能夠經過main方法入口運行程序。
(3)static修飾代碼塊(初始化塊、靜態代碼塊)
格式: static{...}
static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,能夠有多個,位置能夠隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,若是static代碼塊有多個,JVM將按照它們在類中出現的前後順序依次執行它們,每一個代碼塊只會被執行一次。
初始化總結(靜態變量->實例變量->按聲明初始化->執行構造方法)
1)首次使用某個類時,JVM查找相應的類文件並加載(Java只有在必要時纔會逐步載入相應的類文件)
首先爲全部的靜態變量分配存儲空間並初始化爲默認值(全局變量),而後按照聲明靜態變量時指定的初始化動做的順序,以及靜態初始化塊中的語句在類定義中出現的順序依次執行。這些靜態的初始化動做只會在其所屬類的類文件加載時執行一次。
2)類文件加載完畢後,若是須要建立類的對象,則進行以下初始化動做
JVM爲全部的實例變量分配足夠的存儲空間並初始化爲默認值(局部變量);而後按聲明實例變量時指定初值的初始化動做和實例初始化塊中的語句在類中出現的順序依次執行,以後再調用相應的構造方法。
4. abstract和 interface對比
abstract class和interface是支持抽象類定義的兩種機制。正是因爲這兩種機制的存在,才賦予了Java強大的面向對象能力。abstract class和interface之間在對於抽象類定義的支持方面具備很大的類似性,區別:
抽象類(Abstract Class):
(1)只能做爲其餘類的基類,不能被實例化(new);
(2)抽象類中的成員是否是abstract無所謂,並非必須的。(能夠有抽象成員,也能夠沒有任何抽象成員)
(3)抽象類不能同時是final的。抽象的老是但願被繼承,而final類不可被繼承。final和abstract不可同時存在。
(4)非抽象類繼承抽象類,必須覆蓋其全部的抽象成員。抽象類繼承抽象類,能夠不覆蓋全部的抽象成員。
(5)抽象類容許被聲明
接口(interface):
接口的本質是一種特殊的抽象類,用來描述系統對外提供的全部服務。
(1)接口中,全部方法都是公開、抽象的:public abstract。(都必須被繼承)
(2)接口中,全部屬性都是公開、靜態、常量:public static final,且必須賦初值。(全部實現類共享且不可改變)
接口老是但願被實現被訪問的,所以全部成員都必須是公開的(public),確保外界能夠訪問。接口僅僅描述系統能夠作什麼,但不指明如何去作,具體操做由實現類完成,所以方法都是abstract的,都必須被繼承;接口不涉及任何的實現細節,所以無構造方法,接口不能被實例化;無變量,只有靜態常量(static final),由於要被全部的實現類共享;類的繼承只能單繼承,可是接口能夠一次實現多個,用「,」隔開。
5. super和 this對比
super:
super能夠理解爲是指向本身父類對象的一個指針,指的是離本身最近的一個父類。
用法:
this:
this能夠理解爲指向當前對象自身的一個指針,即當前正在執行本方法的那個對象實例。位於函數體內部。
用法:
引用構造函數時:
super(參數):調用父類中的某一個構造函數(應該爲構造函數中的第一條語句)。this(參數):調用本類中另外一種形式的構造函數(應該爲構造函數中的第一條語句)。
this和super都無需聲明。
6. synchronize和 volatile對比
(1)做用範圍:volatile僅能使用在變量級別;synchronized則可使用在變量、方法、和類級別;
(2)volatile本質是在告訴jvm當前變量在寄存器(工做內存)中的值是不肯定的,須要從主存中讀取;synchronized則是鎖定當前變量,只有當前線程能夠訪問該變量,其餘線程被阻塞住。
(3)volatile不會形成線程的阻塞;synchronized可能會形成線程的阻塞。
(4)volatile只能在線程內存和主內存之間同步一個變量的值,而synchronized則同步在線程內存和主內存之間的全部變量的值,經過鎖住和釋放監聽器來實現。
(5)volatile標記的變量不會被編譯器優化;synchronized標記的變量能夠被編譯器優化
(6)顯然,synchronized在性能上將比volatile更加有所消耗
(7)volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則能夠保證變量的修改可見性和原子性
7. String、StringBuffer、StringBuilder對比
(1)可變與不可變
String類中使用字符數組保存字符串,以下就是,由於有「final」修飾符,因此能夠知道string對象是不可變的。
private final char value[];
StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,以下就是,可知這兩種對象都是可變的。
char[] value;
(2)是否多線程安全
String中的對象是不可變的,也就能夠理解爲常量,顯然線程安全。
AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操做,如expandCapacity、append、insert、indexOf等公共方法。
StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。看以下源碼:
public synchronized StringBuffer reverse() { super.reverse(); return this; } public int indexOf(String str) { //存在 public synchronized int indexOf(String str, int fromIndex) 方法 return indexOf(str, 0); }
StringBuilder並無對方法進行加同步鎖,因此是非線程安全的。
(3)StringBuilder與StringBuffer共同點
StringBuilder與StringBuffer有公共父類AbstractStringBuilder(抽象類)。
抽象類與接口的其中一個區別是:抽象類中能夠定義一些子類的公共方法,子類只須要增長新的功能,不須要重複寫已經存在的方法;而接口中只是對方法的申明和常量的定義。
StringBuilder、StringBuffer的方法都會調用AbstractStringBuilder中的公共方法,如super.append(...)。只是StringBuffer會在方法上加synchronized關鍵字,進行同步。
最後,若是程序不是多線程的,那麼使用StringBuilder效率高於StringBuffer。
關於String、StringBuffer、StringBuilder
參考轉載:http://www.cnblogs.com/xudong-bupt/p/3961159.html
http://www.cnblogs.com/xudong-bupt/p/3961159.html
Java中String、StringBuffer、StringBuilder區別與理解
1、先比較String、StringBuffer、StringBuilder變量的HashCode值
使用System.out.println(obj.hashcode())輸出的時對象的哈希碼,
而非內存地址。在Java中是不可能獲得對象真正的內存地址的,由於Java中堆是由JVM管理的不能直接操做。
只能說此時打印出的Hash碼錶示了該對象在JAVA虛擬機中的內存位置,
Java虛擬機會根據該hash碼最終在真正的的堆空間中給該對象分配一個地址.
可是該地址 是不能經過java提供的api獲取的
String變量鏈接新字符串會改變hashCode值,變量是在JVM中「鏈接——斷開」;
StringBuffer變量鏈接新字符串不會改變hashCode值,由於變量的堆地址不變。
StringBuilder變量鏈接新字符串不會改變hashCode值,由於變量的堆地址不變。
小結:哈希碼相同的變量,其內容不必定相同;內容向同變量,哈希碼不必定相同;
public class Buffer_HashCode01 { public static void main(String[] args) { String str1="學海無涯苦做舟"; System.out.println("String 的 str1的hascode"+str1.hashCode()); str1=str1+"人間正道是滄桑"; //注意此str1的存儲地址已發生變化 System.out.println("String 的 str1的hascode"+str1.hashCode()); System.out.println(str1); StringBuffer sb1=new StringBuffer("弟子規"); System.out.println("原來StringBuffer 的 hascode:"+sb1.hashCode()); StringBuffer sb2=sb1.append("聖人教"); //注意sb1和sb2指向同一個地址 System.out.println("添加字符串後StringBuffer 的 hascode:"+sb2.hashCode()); sb2.insert(6,"海納百川"); StringBuilder sb=new StringBuilder("這顯然是上半年"); System.out.println("改變前StringBuilder變量的hashCode值"+sb.hashCode()); sb.append("哦是的啊"); System.out.println("改變後StringBuilder變量的hashCode值"+sb.hashCode()); } } 結果: String 的 str1的hascode-2054942391 String 的 str1的hascode895667206 學海無涯苦做舟人間正道是滄桑 原來 StringBuffer 的 hascode:1311053135 添加字符串後StringBuffer 的 hascode:1311053135 改變前StringBuilder變量的hashCode值118352462 改變後StringBuilder變量的hashCode值118352462
2、比較String、StringBuffer、StringBuilder性能(僅在繁複操做)
String類因爲Java中的共享設計,在修改變量值時使其反覆改變棧中的對於堆的引用地址,因此性能低。
StringBuffer和StringBuilder類設計時改變其值,其堆內存的地址不變,避免了反覆修改棧引用的地址,其性能高。
其中StringBuilder是專門相似於StringBuffer類的非線性安全類,即StringBuffer是線性安全的,適合於多線程操做;
StringBuilder是線性不安全的,適合於單線程操做,其性能比StringBuffer略高。
public class Xing_Neng_SSS01 { public static void main(String[] args) { long begin1 = System.currentTimeMillis(); String str = ""; for(int i=0;i<10000;i++){ str = str+i; } long end1 = System.currentTimeMillis(); long time1 = end1 - begin1; System.out.println("一、String + time="+time1); long begin2 = System.currentTimeMillis(); String str2 = ""; for(int i=0;i<10000;i++){ str2 = str2.concat(i+""); } long end2 = System.currentTimeMillis(); long time2 = end2 - begin2; System.out.println("二、String concat time="+time2); long begin3 = System.currentTimeMillis(); StringBuffer str3 = new StringBuffer(); for(int i=0;i<10000;i++){ str3.append(""+i); } long end3 = System.currentTimeMillis(); long time3 = end3 - begin3; System.out.println("三、StringBuffer time="+time3); long begin4 = System.currentTimeMillis(); StringBuilder str4 = new StringBuilder(); for(int i=0;i<10000;i++){ str4.append(""+i); } long end4 = System.currentTimeMillis(); long time4 = end4 - begin4; System.out.println("四、StringBuilder time="+time4); } } 結果: 一、String + time=241 二、String concat time=92 三、StringBuffer time=4 四、StringBuilder time=2
3、String共享設計
當String使用引號建立字符串時,會先去字符串池中找,找到了就返回,找不到就在字符串池中增長一個而後返回,這樣因爲共享提升了性能。
而new String()不管內容是否已經存在,都會開闢新的堆空間,棧中的堆內存也會改變。
下面是==來比較地址是否相等。
public class String_Equals01 { public static void main(String[] args) { String str1="學海無涯苦做舟人間正道是滄桑"; String str11=str1; String str12="學海無涯苦做舟人間正道是滄桑"; String str13=new String("學海無涯苦做舟人間正道是滄桑"); System.out.println("String 的 str1 的hascode"+str1.hashCode()); System.out.println("String 的 str11的hascode"+str11.hashCode()); System.out.println("String 的 str12的hascode"+str12.hashCode()); System.out.println("String 的 str13的hascode"+str13.hashCode()); System.out.println("str1==str11 "+(str1==str11)); System.out.println("str1==str12 "+(str1==str12)); System.out.println("str1==str13 "+(str1==str13)); } } 結果: String 的 str1 的hascode895667206 String 的 str11的hascode895667206 String 的 str12的hascode895667206 String 的 str13的hascode895667206 str1==str11 true str1==str12 true str1==str13 false