【計算機基礎】Java學習篇(四) 認識類與物件(打包器、陣列和字串)
介紹完基本型別,下面介紹類型別。
瞭解物件與參考的關係,認識打包器,以及陣列物件、字串物件。
一、類與物件
1.建立類
編寫程式需要使用物件(Object),產生物件必須先定義類(Class),類就像是設計圖,而物件是類的一個例項。(Instance)
類定義用關鍵詞class。比如定義一個衣服類:class Clothes;
新建一個物件:new Clothes();
要給物件起名字:Clothes c;術語稱:宣告參考名稱(Reference Name)或參考變數(Reference Variable)
這個名字要和新建的物件進行繫結。術語稱:將c名稱參考(Refer)至新建物件,用“=”指定。
new Clothes()= Clothes c;
類擁有自己的變數,也叫作域(Field)成員、資料成員。比如衣服的顏色和尺碼。
class Clothes{ String color; char size; }
我們建立好物件後可以用 物件名.資料成員的格式指定值。 比如c.color="red";
2.介紹兩個基本標準類
1)獲取使用者輸入 java.util.Scanner
用System.in物件的read()方法可以取得使用者輸出,但此方法是以int型別返回讀入的字元編碼。
還是用Scanner ——————————————————————————
Scanner scanner=new Scanner(System.in); // 建立例項,同時必須傳入java.io.InputStream的例項。
scanner物件會幫你掃描標準輸入。
獲取輸入:使用方法 nextInt()、nextByte()、nextFloat()……
獲取整行:nextLine()
2)java.math.BigDecimal
Java語言遵守IEEE754浮點數運算(Floating-Point Arithmetic),使用分數和指數來表示浮點數。
0.5用1/2表示;0.75用1/2+1/4表示;0.875用1/2+1/4+1/8表示;0.1用1/16+1/32+1/256+1/512+1/4096…無限迴圈累加表示。因此,由於浮點數誤差的關係,double 0.1相加 ≠ 0.2,為了有更好的精確度,使用這個類。
BigDecimal a =new BigDecimal(“1.0”); // 建立物件 BigDecimal b =new BigDecimal(“0.8”); BigDecimal result =a.plus(b); // 呼叫方法
加減乘除 plus()、substract()、multply()、divide()
因為做完運算後,還是BigDecimal型別,所以可以連續運算。
3)剩下還有許許多多的類和方法,我們可以查詢Java API文件來了解。在搜尋引擎查詢更方便。
3.物件指定與相等性
區分一下=和==的不同。(底層記憶體的實際運作沒有不同)
對於基本型別,=是值複製;==是比較兩個變數的值。
對於類型別的物件,=是指定參考名稱參考某個物件;==是比較兩個參考名稱是否參考同一個物件。
判斷物件的值是否相同可以用equals()方法。
三、基本型別打包器
1.打包基本型別
基本型別 int、long、double、float、boolean,使用在於效率,然而很多時候我們操縱的都是物件,物件能攜帶更多資訊。
我們需要使用Integer、Long、Double、Float、Boolean等類打包成物件來操作。這些所謂的類即打包器(Wrapper)目的就是提供物件例項作為“殼”。
打包器是類,是Number抽象類的子類,擁有自己的方法,在java.lang包裡。
int a=10; Integer aa=new Integer(a); // 打包基本型別
打包器可以使用方法,如doubleValue()將打包值以double型別返回,這樣可以進行運算。
比較Number類的物件值大小,使用compareTo(),如a.compareTo (b),值相同為0,小於為-1,大於為1
2.自動裝箱與拆箱
J2SE 5以後支援自動裝箱(Autoboxing)、拆箱(Unboxing)。
比如:自動裝箱Integer a=10;可以直接使用,執行時會參考Integer的例項。
自動拆箱:int b = a; 自動取得打包的int型別再指定給b。
運算也可以自動裝箱、拆箱: int型別和Integer型別可以相互運算。
3.自動裝箱拆箱的內幕
實質是編譯程式蜜糖(Compiler Sugar),也就是說寫的方便,編譯的時候會將程式程式碼展開。
比如Integer num=100;編譯程式會展開為,Integer localInteger = Integer.valueOf(100);
(我們可以通過反編譯程式比如JD、JAD來看到)
※ 自動拆箱實際程式碼 intValue()
比如,Integer i = null; int j=i;這兩句編譯沒有問題,但是執行會產生NullPointerException空指向錯誤。
實際程式碼是:Object localObject=null;int i=localObject.intValue();
也就是說實質上建立了一個空物件,然後進行設值,然而null是特殊物件,是空的,這個名稱沒有參考到任何物件實體上,所以無法呼叫方法。
※ 自動裝箱實際程式碼 valueOf()
比如,Integer i1=100;Integer i2=100;那麼i1是否等於i2呢?答案是:i1=i2。
Integeri1=200; Integer i2=200;換了數值答案卻是i1≠ i2。
實際程式碼是打包器呼叫了valueOf(int i)這個方法進行拆箱。這個方法的意思是如果傳入的int在IntegerCache.low(-128)與IntegerCache.high(127)之間,那就嘗試看前面快取(Cache)中有沒有打包過相同的值,如果有就返回。
明白了其中的原理,我們也就明白了為什麼100和200的兩個物件會不一樣,因為i2在100的時候會從前面i1的快取中直接傳回Integer例項。而i2=200的時候就要重新建立例項了。
當然,數值也是可以修改的。自行查閱。
三、陣列物件
1.陣列基礎
陣列基本上是用來收集資料的,是具有索引的資料結構。索引i從0開始。
宣告陣列建議把[ ]放在類關鍵詞的後面。這是Java的開發習慣。
陣列建立方法一:int[ ] a={1,2,3,4,5};
指定索引:a[i]
陣列長度:a.length
遍歷輸出每一個元素:for迴圈。(但只是從頭遞增到尾,和索引值毫無關係)
循序的輸出陣列值:增強式for迴圈(Enhanced for Loop)
語法:for(int x:陣列名){
輸出x}
編譯程式蜜糖。實際程式碼是把原陣列複製到新陣列上,然後用新陣列的長度進行for迴圈遍歷,把遍歷的值存給一個int變數進行輸出。
二維陣列宣告並賦值:int[ ] [ ] a={
{1,2,3},
{4,5,6}
};
指定索引:a[x] [y]
有幾行:a.length
一行多長:a[x].length
遍歷輸出每一個元素:雙重for迴圈,外迴圈用x<a.length迴圈列,內迴圈用y<a[x].length迴圈每列的元素,最後輸出a[x][y]
循序的輸出陣列值:增強式for迴圈。
for(int[ ] x:a){ // 抽出每一個組 for(int y:x){ // 抽出每一個元素 輸出 y } }
2.陣列物件
前面介紹了陣列基礎知識,下面我們把陣列看作物件。
建立陣列方法二:int[ ] a=new int[2] // 定義陣列可以用int[ ] a;但建立物件必須指定陣列長度。
建立陣列方法三:int[ ] a=new int [ ] {0,0}; // 賦值書寫,不用指定陣列長度
不同的型別的陣列元素有不同的初始值,我們可以使用java.util.Arrays的fill()方法設定新的初始值。
Arrays.fill(陣列名,初始值);
建立陣列物件的類定義是由JVM動態產生。
下面看二維陣列。
實際上,Java的多維陣列都是由一維陣列組成。我們可以看作是int[ ] [ ] a;
比如int[ ] [ ] a=new int[2] [3]{
{1,2,3},
{4,5,6}
};
定義兩個一維陣列,每個陣列能存三個值。
術語也就是,其中有2個int[ ]型別的索引,分別參考了長度為3的一維陣列。
a.length等同於陣列a的參考物件有幾個索引,即也就是有幾個一維陣列。
a[x].length等同於索引x的參考物件的長度,即這個一維陣列的元素個數。
當然二維陣列也可以是不規則陣列,不一定是矩陣。
int[ ] [ ] a=new int[2] [ ];
a[0] =new int[ ]{1,2,3};
a[1]=new int[ ]{1,2};
這段程式碼先宣告有兩個索引,每個索引對應的物件都是null,即建立0個物件,再分別參考一維陣列。
以上都是基本型別的例子,類型別也是同理,且可以結合自動裝箱而省略new物件。
3.陣列複製
首先我們明白陣列是物件,所以用=不是複製,而是繫結參考。
基本型別陣列的複製:
1、建立一個和原陣列等長的新陣列。int [ ] b=new int [a.length],然後for迴圈複製。
2、建立等長新陣列,使用System.arraycopy(源陣列,源陣列的起始索引,目的陣列,目的陣列的起始索引,複製長度),這個方法有五個引數,使用原生方法複製比迴圈要快。
3、不用建立新陣列,使用更方便的Arrays.copyOf(),可以自由建立更長的陣列。
int[ ] 新陣列名=Array.copyOf(源陣列名,新陣列長度)
類型別陣列的複製:
1、淺層複製(Shallow Copy):for迴圈內,每個陣列物件複製,c2[i] = c1[i]。
複製陣列索引的物件,即複製了原陣列物件的參考,改變原陣列物件的資料成員,新陣列的物件也會改變。繫結在了一起。使用上面的兩個方法應用在類型別陣列,也一樣是淺層複製。
2、深層複製(Deep Copy):for迴圈內,型別 c=new 型別(原陣列名[i].資料成員,……);新陣列名[i]=c;
重新建立物件,包括資料成員進行復制。即複製的物件也有自己的資料成員。
四、字串物件
1.字串基礎
1)字串:由字元組成的文字元號
2)本質:打包字元陣列的物件。是java.lang.String的例項。可以用雙引號建立。
3)String類的幾個方法:長度length(),顯示索引字元charAt(0),轉換大寫toUpperCase()
4)字串與字元陣列的相互轉換:
作參new一個String例項:String 字串名=new String(字元陣列名);
呼叫方法拆穿字元陣列 :char[ ] 字元陣列名=字串名.toCharArray();
5)字串解析成基本型別的方法:XXX.parseXXX(字串)。比如可以通過鍵盤輸入,解析成基本型別進行操作,但如果你的字串不包含可以轉換的基本型別,則會丟擲數字格式化錯誤NumberFormatException這個異常。
6)程式進入點main()中的String[ ] args
在啟動JVM的時候,指定執行類的同時,還可以指定命令自變數(Command Line Arguments),
在命令列指定:>java com.faceno.FirstString 1 2 3 4
在IDE指定:專案配置引數
指定以後,這些自變數會收整合String陣列,由args參考。
相當於內建的String字串陣列,儲存初始化引數。