標籤:浮點型 java upload har block 使用 封裝類 效率 short
一、四大基礎資料型別 (Elementary Data Type):
1、邏輯性boolean:
boolean類型的資料只允許取值true or false,不可以用0或非0代替。
2、字元型char:
字元常量用單引號括起來的單個字元,例如:
1 char weChar = ‘a‘;2 char weChar = ‘我‘;
3、整數型(byte、short、int、long)
十進位整數,如:12,-314,0;
八進位整數,要求以0開頭,如:012;
十六進位整數,要求以0x或0X開頭,如:0x12。
Java語言的整型常量預設為int型,聲明long型常量可以後加‘l’或‘L’,如:
1 int i1 = 600;
2 long i2 = 88888888888888L;
4、浮點型(float、double)
java浮點型常量預設為double型,如要聲明一個常量為float型,則需要在數字後面加f或F,如:
1 double d = 1234.9;2 float f =123.3f;
5、特殊的String類型
Java中String是一個特殊的封裝類資料,它有如下兩種建立形式:
1.String s = "abc";
第一種:首先在棧中建立一個對String類的對象引用變數s,然後去尋找“abc”是否被儲存在字串常量池當中,如果沒有則在棧中建立三個char型的值‘a‘、‘b‘、‘c‘,然後在堆中建立一個String對象object,它的值就是剛才在棧中建立的三個char型值組成的數組{‘a’、‘b‘、‘c‘},接著這個String對象object被存放進字串常量池,最後將s指向這個對象的地址。如果‘abc‘已經被儲存在字串常量池中,則在字串常量池中找到值為‘abc‘的對象object,然後將s指向這個對象的地址。
記憶體
這種建立方式的特點是:jvm會自動根據常量池中的情況來決定是否有必要建立新對象。
2.String s = new String("abc");
第二種建立方法可以分解為兩步:
①String object = "abc";
②String s = new String(object);
第一步參考第一種建立方法,而第二部由於“abc”已經被建立並儲存到字串常量池中,因此jvm只會在堆中新建立一個String對象,它的值共用棧中已有的三個char型值。
在將字串比較前,必須要瞭解==和equals的區別:
對於String類來說,用於比較兩個String對象的地址,equals則用於比較兩個String對象的內容值。
例1:字串常量池的使用
1 String s0 = "abc";2 String s1= "abc";3 System.out.println(s0==s1);//true 可以看出s0和s1是指向同一個對象的。
例2:String中==與equals的區別
1 String s0 =newString ("abc"); 2 String s1=newString ("abc"); 3 System.out.println(s0==s1);//false 可以看出用new的方式是產生不同的對象4 System.out.println(s0.equals(s1));//true 可以看出equals比較的是兩個String對象的內容(值)
例3:編譯期確定
1 String s0="helloworld";2 String s1="helloworld";3 String s2="hello" + "world";4 System.out.println( s0==s1 );//true 可以看出s0跟s1是同一個對象5 System.out.println( s0==s2 );//true 可以看出s0跟s2是同一個對象
分析:因為例子中的s0和s1中的"helloworld”都是字串常量,它們在編譯期就被確定了,所以s0==s1為true;而"hello”和"world”也都是字串常量,當一個字串由多個字串常量串連而成時,它自己肯定也是字串常量,所以s2也同樣在編譯期就被解析為一個字串常量,所以s2也是常量池中"helloworld”的一個引用。所以我們得出s0==s1==s2;
例4:編譯期無法確定
1 String s0="helloworld";2 String s1=newString("helloworld");3 String s2="hello" +newString("world");4 System.out.println( s0==s1 );//false5 System.out.println( s0==s2 );//false6 System.out.println( s1==s2 );//false
分析:用new String() 建立的字串不是常量,不能在編譯期就確定,所以new String() 建立的字串不放入常量池中,它們有自己的地址空間。s0還是常量池中"helloworld”的引用,s1因為無法在編譯期確定,所以是運行時建立的新對象"helloworld”的引用,s2因為有後半部分new String(”world”)所以也無法在編譯期確定,所以也是一個新建立對象"helloworld”的引用;
例5:編譯期最佳化
1 String s0 = "a1";2 String s1= "a" + 1;3 System.out.println((s0== s1));//result = trueString s2 = "atrue";4 String s3= "a" + "true";5 System.out.println((s2== s3));//result = trueString s4 = "a3.4";6 String s5= "a" + 3.4;7 System.out.println((a== b));//result = true
分析:在程式編譯期,JVM就將常量字串的"+"串連最佳化為串連後的值,拿"a" + 1來說,經編譯器最佳化後在class中就已經是a1。在編譯期其字串常量的值就確定下來,故上面程式最終的結果都為true。
例6:編譯期無法確定
1 String s0 = "ab";2 String s1= "b";3 String s2= "a" +s1;4 System.out.println((s0== s2));//result = false
分析:JVM對於字串引用,由於在字串的"+"串連中,有字串引用存在,而引用的值在程式編譯期是無法確定的,即"a" + s1無法被編譯器最佳化,只有在程式運行期來動態分配並將串連後的新地址賦給s2。所以上面程式的結果也就為false。
例7:編譯期確定
1 String s0 = "ab";2 final String s1 = "b";3 String s2= "a" +s1;4 System.out.println((s0== s2));//result = true
分析:和[6]中唯一不同的是s1字串加了final修飾,對於final修飾的變數,它在編譯時間被解析為常量值的一個本地拷貝儲存到自己的常量 池中或嵌入到它的位元組碼流中。所以此時的"a" + s1和"a" + "b"效果是一樣的。故上面程式的結果為true。
例8:編譯期無法確定
1 String s0 = "ab";2 final String s1 = getS1();3 String s2= "a" +s1;4 System.out.println((s0== s2));//result = false5 private static String getS1() {return "b";}
分析:JVM對於字串引用s1,它的值在編譯期無法確定,只有在程式運行期調用方法後,將方法的傳回值和"a"來動態串連並分配地址為s2,故上面 程式的結果為false。
關於String的不可變設計:
String是不可改變類(記:基本類型的封裝類都是不可改變的)的典型代表,也是Immutable設計模式的典型應用,String變數一旦初始化後就不能更改,禁止改變對象的狀態,從而增加共用對象的堅固性、減少對象訪問的錯誤,同時還避免了在多線程共用時進行同步的需要。
Immutable模式的實現主要有以下兩個要點:
1.除了建構函式之外,不應該有其它任何函數(至少是任何public函數)修改任何成員變數。
2.任何使成員變數獲得新值的函數都應該將新的值儲存在新的對象中,而保持原來的對象不被修改。
String的不可變性導致字串變數使用+號的代價:
例9:
1 String s = “a” + "b” + "c”;2 String s1= "a";3 String s2= "b";4 String s3= "c";5 String s4= s1 + s2 + s3;
分析:變數s的建立等價於 String s = “abc”; 由上面例子可知編譯器進行了最佳化,這裡只建立了一個對象。由上面的例子也可以知道s4不能在編譯期進行最佳化,其對象建立相當於:
1 StringBuffer temp = new StringBuffer();2 temp.append(s1).append(s2).append(s3);3 String s = temp.toString();
由上面的分析結果,可就不難推斷出String 採用串連運算子(+)效率低下原因分析,形如這樣的代碼:
1 public class Test {2 public static void main(String args[]) {3 String s=null;4 for(inti = 0; i < 100; i++) {5 s+= "a";6 }7 }8 }
每做一次 +就產生個StringBuffer對象,然後append後就扔掉。下次迴圈再到達時重新產生個StringBuffer對象,然後append字串,如此迴圈直至結束。如果我們直接採用StringBuffer對象進行append的話,我們可以節省N -1次建立和銷毀對象的時間。所以對於在迴圈中要進行字串連線應用程式,一般都是用StringBuffer或StringBulider對象來進行append操作。
java基礎學習——1、基礎資料型別 (Elementary Data Type)