mybatisplus修改单个属性_第二节官封弼马温——类的属性
《西游記》第2集 官封弼馬溫
美猴王戰勝了混世魔王,花果山上喜氣洋洋,小猴們每日操演武藝,十分快樂。悟空闖入東海龍宮,向龍王索取鎮海神針——如意金箍棒。這棒雖重一萬三千五百斤,卻大可撐天著地,小可變針,藏入耳內。悟空酒醉睡去,忽見兩個陰差前來索命,悟空大鬧閻羅殿,命判官取出生死簿,一筆勾去了猴類的生年死月。龍王、閻王上玉帝處告狀,玉帝派太白金星下界招撫猴王,請他上天作官。悟空欣然前往,在武曲星君的捉弄下,玉帝封他做了弼馬溫。當悟空明白了自己不過是個馬夫后,大怒之下回轉花果山,扯起大旗,自稱齊天大圣。玉帝不能容忍,叫托塔天王與哪吒率領天兵神將,殺向花果山。
1.類的屬性定義
前面說過,對象有它自己的屬性。屬性是對象具有的各種特征,每個對象的每個屬性都有特定值,是對于對象的基本信息或是當前狀態等的描述。在Java中,屬性可以是一個常量或者變量,一般的格式如下:
修飾符 屬性類型 屬性名=初始值;(初始值可以沒有)
修飾符是指訪問的權限限制,我們將在下節中講解。
屬性類型可以是一個簡單類型,例如數字(孫悟空的年齡)、字符串(孫悟空的名字)等等,也可以是一個復雜類型,例如數組、集合等,還可以是另一個類,即一個對象可以是另一個對象的屬性,也就是說對象可以是包含的關系。例如,金箍棒是孫悟空所有的一個物品,那么“金箍棒”類即可以定義為“孫悟空”類的一個屬性。
這里希望你可以對屬性有一個感性的認識,稍后我們會將每一種情況詳細展開講解。
把屬性這里補充進去,“孫悟空”類可以寫成:
那么如何在Java中精確定義出這個對象呢?我們首先需要了解Java中的數據類型定義及常量與變量的概念。
2 常量與變量
簡單的說,變量就是在程序運行期間可以修改的量,常量就是在程序運行期間不能被修改的量。
孫悟空有兩個名字,一個是他的本名,一個是他的別名。
孫悟空的本名就是孫悟空,提到“孫悟空”,你就能知道說的是誰,所以這是他的唯一固定標識,不允許被更改,這就是常量。
《西游記》第一回后半部分寫他見到菩提祖師,祖師根據他是猴子(猢猻),為他取名為“孫”,法名“悟空”。他后來聽從觀音菩薩的勸告,拜唐僧為師參加取經,就正式啟用“悟空”這一法號。
孫悟空的別名有很多,像孫行者就是他的別名。《西游記》中有提及,三藏歡喜道:“也正和我們的宗派。你這個模樣,就象那小頭陀一般,我再與你起個混名,稱為行者,好么?”悟空道:“好!好!好!”自此時又稱為孫行者。
在遇到唐三藏之前,他是沒有別名的,在遇到他之后,便有了別名叫孫行者,這就是變量。當然,變量也是有訪問權限限制的,不是誰都可以更改,后面會詳細講述。
除了這兩個名字外,孫悟空還有一些外號,這是別人額外給他起的,像美猴王、孫大圣、潑猴等等。這個同樣是可以改變的,是變量。除此之外,他的職務也是變量,最開始是“弼馬溫”,后來是“齊天大圣”。
2.1 常量
(1)常量表示的是在程序運行過程中不能被程序所修改的數據。
(2)聲明常量必須用final關鍵字。
(3)常量分為:整型,浮點型,字符型,布爾型,字符串型常量。(注意,常量只能是一個值,不能是引用類型,即不能是類和對象)
語法:final <類型> variable=值;
因此,“孫悟空”類的姓名屬性應該改為:
final字符串 姓名=“孫悟空”;
這樣修改后的“孫悟空”類即為:
2.2 變量
為什么需要變量?
電腦使用內存來記憶計算時所使用的數據。數據各式各樣,要先根據數據的需求(即類型)為它申請一塊合適的空間,便有了十六位的內存在址。內存空間的數據有可能會被程序改變,而內存地址不方便記憶,因此產生了變量——即,通過內存中小空間的別名找到數據存儲的位置。
內存地址不好記,怎么辦?
通過內存中小空間的別名找到數據存儲的位置。
一個變量是存儲數據的一個基本單元。
變量的應用即為:
1、在內存中存儲弼馬溫這個職位的數據
2、顯示內存中存儲的數據的值
在“孫悟空”類的屬性中,除了絕對不可改變的姓名外,其他的均是變量。使用一個變量的步驟如下:
變量的聲明和賦值可以是以下兩種:
1.在聲明的同時賦值,格式為:數據類型 變量名 = 數值;
例如“孫悟空”類中的年齡屬性: 數字 年齡=1226;
2.先聲明,后賦值
格式為:數據類型 變量名;
變量名 = 數值;
例如“孫悟空”類中的年齡屬性:
數字 年齡;
年齡=1226;
在Java語言中,變量命名要符合一定規則,由字母、數字、下劃線或美元符號($)組成,但只能由字母、下劃線或美元符號($)開頭,但我建議盡量避免使用$符號。一般是以變量所表達的意義的英文單詞組成,如果多于一個單詞的,第一個單詞首字母小寫,其他單詞的首字母大寫,如下:
變量分為局部變量和成員變量。
局部變量是在方法內定義的變量,只是相應的方法體內或程序塊內有效;成員變量是在類中定義的,即是屬性(又稱全局變量)可以通過對象引用。是哪種變量,主要是看它的定義位置,如果是在類中定義的,那么就在整個類中有效,如果是在類的方法中定義的,就只在方法中有效。這里大家先記下這個作用域的概念,之后講到方法時會更直觀的了解。
局部變量在使用之前,必須先初始化,否則不能直接使用。
成員變量(屬性/全局變量)如果沒有初始化,在使用時,系統將會自動賦一個默認的初始值,如下表:
由上表即可以看到,Java中的數據類型分為基本類型和引用類型,基本類型中除了布爾型的值初始為false外,其他類型的初始值都是0,而引用類型的初始值為null。
null是Java的關鍵字,它的意思就是“空”,代表什么都沒有,后面會再次介紹。在一開始的時候,孫悟空這個對象,“手上拿的東西”這一屬性就是空的(null),直到他闖入東海龍宮,向龍王索取了鎮海神針,這一屬性才有了值:如意金箍棒。
下面我們來講一下Java中的基本類型和引用類型。
3 Java數據類型-基本類型
在Java中代碼中,每個變量都必須聲明一種類型(type)。數據類型分為基本類型(primitive types)和引用類型(reference types)。
3.1 什么是基本類型
Java為基本類型提供語言級別的支持,即已經在Java中預定義,用相應的保留關鍵字表示。基本類型是單個值,而不是復雜的對象,基本類型不是面向對象的,主要出去效率方面的考慮,但是同時也提供基本類型的對象版本,即基本類型的包裝器(wrapper)。可以直接使用這些基本類型,也可以使用基本類型構造數組或者其他自定義類型。基本類型具有明確的取值范圍和數學行為。
即是八個原始數據類型,大體可分為四種:
l 邏輯類 Boolean 布爾型,像孫悟空的臉上是否有毛這個屬性,即屬于布爾型,布爾型的數據選值只能是true(是)和false(否)。
例如:boolean hasHair = true;//將變量truth賦值為真,即的確有毛
l 文本類 char 字符型,注意,這里指的可不是字符串(字符串類型是String,它是對象,不屬于基本類型,而是引用類型,下面會講到),而是單個字符,例如:孫悟空的性別標識,那就應該定義為字符型,取值可以是“男(M)”或者“女(F)” 。字符型的數據以單引號(‘’)包含。
例如:char sex = ‘M’;//孫悟空應該為男性
l 整數類 byte, short, int, long,這四種類型均用來保存整數類的數據,區別只是存儲的數據大小不同,像孫悟空的年齡,定義為short類型即可,具體的數值范圍可以參照下表。
l 浮點類 float,double,這兩種類型均用來保存浮點型的數據(即帶小點數的數字),區別只是存儲的數據大小不同,像孫悟空的體重,可能就不是整數,可以定義為float類型,具體的數值范圍可以參照下面的基本數據類型對比表:
所有的教程都會列出這些數值范圍,但是我相信沒有人能記得住,這里并不需要你背下來,只需要了解一下即可,需要的時候可以速查。
我一直強調,學習編程,并不需要死記硬背,主要是要了解思想(即:知道寫這段代碼的思路),以及對java知識的感性認識(即:知道它有什么,都是做什么用的),在實際應用中,完全可以速查。
畢竟,這不是閉卷考試。
由上面的介紹我們可以判斷出,“孫悟空”類中,以下屬性是基本類型的,包括年齡、臉上是否有毛、屁股上是否有尾巴:
整理一下,Java的數據類型分為三大類,即布爾型、字符型和數值型,而其中數值型又分為整型和浮點型,Java的變量類型為布爾型boolean;字符型char;整型byte、short、int、long;浮點型float、double。
在Java中,整型、實型、字符型等這些基本數據類型。按存儲空間(即能存儲數值的大小)由低級到高級分別為:
(byte,short,char )->int->long->float->double。
3.2類型轉換
四種整型變量和兩種浮點型變量分別對應于不同的精度和范圍。此外,我們還經常用到一種類變量,即String。下面的論述中,我們將闡述如何實現這些轉換。
數據類型之間的轉換方式有如下三種:
l 低級到高級的自動類型轉換
l 高級到低級的強制類型轉換
l 包裝類過渡類型轉換
下面我們來分別講解:
自動類型轉換
低級變量可以直接轉換為高級變量,稱之為自動類型轉換。自動轉換時發生擴寬(widening conversion)。因為較大的類型(如int)要保存較小的類型(如byte),內存總是足夠的,不需要強制轉換。如果將字面值保存到byte、short、char、long的時候,也會自動進行類型轉換。注意區別,此時從int(沒有帶L的整型字面值為int)到byte/short/char也是自動完成的,雖然它們都比int小。在自動類型轉化中,除了以下幾種情況可能會導致精度損失以外,其他的轉換都不能出現精度損失。
int型數據--> float
long型數據--> float
long型數據--> double
float型數據 -->double without strictfp
除了可能的精度損失外,自動轉換不會出現任何運行時(run-time)異常,異常會在后面章節講解,這里可以理解為不會發生錯誤。
例如:
byte b;
int i=b;
long l=b;
float f=b;
double d=b;
完全可以直接去賦值,默認即可完成轉換,不會出錯。
強制類型轉換
如果將高級變量轉換為低級變量時,或者在同級的short與char之間進行轉換,就必須強制轉換,也被稱作縮小轉換(narrowing conversion),因為必須顯式地使數值更小以適應目標類型。強制轉換采用轉換操作符()。嚴格地說,將byte轉為char不屬于narrowing conversion),因為從byte到char的過程其實是byte-->int-->char,所以widening和narrowing都有。強制轉換除了可能的精度損失外,還可能使模(overall magnitude)發生變化。強制轉換格式如下:
(target-type) value
例如:
// 定義short 整型變量 i 并且賦值
short i=99;
// 將 i 強制類型轉換為 char 型變量
char c=(char)i;
如果整數的值超出了byte所能表示的范圍,結果將對byte類型的范圍取余數。例如a=256超出了byte的[-128,127]的范圍,所以將257除以byte的范圍(256)取余數得到b=1;需要注意的是,當a=200時,此時除了256取余數應該為-56,而不是200.
將浮點類型賦給整數類型的時候,會發生截尾(truncation)。也就是把小數的部分去掉,只留下整數部分。此時如果整數超出目標類型范圍,一樣將對目標類型的范圍取余數。
基本類型轉換總結如下圖:
注:藍色的部分為正常轉換,黃色的部分為會發生截尾。
包裝類過渡類型轉換
什么是包裝類?
包裝類,就是可以直接將簡單類型的變量表示為一個類
在執行變量類型的相互轉換時,我們會大量使用這些包裝類
Java共有六個包裝類,分別是Boolean、Character、Integer、Long、Float和Double,分別對應于 boolean、char、int、long、float和double
String本身就是類。所以也就不存在什么包裝類的概念了
在進行簡單數據類型之間的轉換(自動轉換或強制轉換)時,可以利用包裝類進行中間過渡。
一般情況下,首先聲明一個變量,然后生成一個對應的包裝類,就可以利用包裝類的各種方法進行類型轉換了。
簡單類型的變量轉換為相應的包裝類,可以利用包裝類的構造函數。即:
? Boolean(boolean value)orBoolean(String value)
? Character(char value)orCharacter(String value)
? Integer(int value)orInteger(String value)
? Long(long value)orLong(String value)
? Float(float value)orFloat(String value)
? Double(double value)orDouble(String value)
而在各個包裝類中,有xxxValue()的方法,來得到其對應的簡單類型數據。利用這種方法,也可以實現不同數值型變量間的轉換。
例如,對于一個雙精度實型類,intValue()可以得到其對應的整型變量,而doubleValue()可以得到其對應的雙精度實型變量。
所有類中均提供了toString()方法,即將該類轉換為字符串。例如:Characrer,Integer,Float,Double,Boolean,Short等類的toString()方法用于將字符、整數、浮點數、雙精度數、邏輯數、短整型等類轉換為字符串。
在實際程序應用中,最常用的就是各個基本類型與字符串(String)間的轉換。一般由字符串轉換成基本類型,使用各個包裝類中的xxxValue()或者parseXXX()方法,例如:
String a = "55";
//將上面的字符串轉換成整型
int i1 = new Integer(a).intValue();//使用包裝類所生成對象的xxxValue()方法
int i2 = Integer.parseInt(a);//使用包裝類的parseXXX()方法
而在將基本類型轉換成字符串時,多使用包裝類toString()方法以及String類的valueOf()方法。例如:
int i= 55;
//將上面的整型數據轉換成字符串
String a1 = new Integer(i).toString();//包裝類所生成對象的toString()方法
String a2 = String.valueOf(i);//使用String類的valueOf()方法
需要生成對象再調用的叫做實例方法,而通過類名直接調用的稱為類方法。上面我們學到過,通過new關鍵字可以生成對象,因此可以看得出,上面的xxxValue()和toString()方法就是實例方法,而parseXXX()和valueOf()是通過類名直接調用的,屬于類方法,關于實例方法與類方法,請先有個基本的使用區分,我們在下面章節再詳細講解。
很多人都會覺得字符串也應該是基本類型的,因為這個是最常用的,但是在Java中,沒有內置這個類型,字符串常量是作為String類的對象存在的,因此它屬于引用類型,下面我們便來講解引用類型。
4 Java數據類型-引用類型
4.1 什么是引用類型
引用類型就是指類型不是基本類型,而是一個類類型的數據,比如“孫悟空”類中的字符串類型以及“金箍棒”類類型。你也可以這樣理解,除了上面講到的基本類型之外,任何其他的類型定義均為引用類型。
4.2 字符串
字符串指的是字符的序列。前面說過,在Java中,沒有內置的字符串類型,字符串常量是作為String類的對象存在的。因此,每個屬性均相當于創建了一個String類對象。
之前我們接觸過,每個類都有一個或多個構造函數,String類也不例外,在創建String類對象時,通常需要向構造函數傳遞參數來指定創建的字符串的內容,常用的String類構造函數:
public String():該構造函數用于創建一個空的字符串常量。
public String(String value):該構造函數用于根據一個已經存在的字符串常量來創建一個新的字符串常量,該字符串的內容和已經存在的字符串常量一致。
String(byte[] bytes, String charsetName) :該構造函數構造一個新的 String,使用指定的字符集解碼指定的字節數組。
public String(char value[]):該構造函數用于根據一個已經存在的字符數組來創建一個新的字符串常量。(數組將在本章后面的內容中介紹)
public String(StringBuffer buffer):該構造函數用于根據一個已經存在的StringBuffer對象來創建一個新的字符串常量。StringBuffer是變長的字符串,將在下面講解。
由于字符串是最常用的一種類型,因此Java中增加了便捷的定義方式:
前面我們講過,既然是類,那么就會有相應的操作方法,String類對象的常用操作及方法如下:
? int indexOf(String str):返回第一次出現的指定子字符串在此字符串中的索引
例如,想查尋“孫悟空”這個字符串中,姓所在的位置,那么就可以用此方法:
String str = "孫悟空";
int index = str.indexOf("孫");
得到的結果就是0。Java語言中,所有標號是從0開始的,因此第一個位置的標號為0。包括數組、循環等都是從0開始的。
? int indexOf(String str, int fromIndex):從指定的索引處開始,返回第一次出現的指定子字符串在此字符串中的索引。如果被查詢的字符串僅出現一次,那么這個方法與上面的方法返回的結果是相同的,但是如果出現了不止一次,那么將會有不同的返回結果。
例如,想查尋“孫悟空打敗了假孫悟空”這個字符串中,“空”所在的位置,那么就可以看出差別:
String str = "孫悟空打敗了假孫悟空";
int index1 = str.indexOf("空");//結果為2
int index2 = str.indexOf("空", 4); //結果為9
這種方法名相同,但是參數不同的方法,叫做方法的重載,將在下面講到Java的多態時詳細講解。
? int lastIndexOf(String str):返回最后一次出現的指定字符串在此字符串中的索引。
例如,想查尋“孫悟空打敗了假孫悟空”這個字符串中,“空”最后一次的位置:
String str = "孫悟空打敗了假孫悟空";
int index1 = str.lastIndexOf("空");//結果為9
? int lastIndexOf(String str, int fromIndex):從指定的索引處開始進行反向搜索,就是相當于限定了搜索的范圍是在0與fromIndex之間,結果仍然是返回最后一次出現的指定字符串在此字符串中的索引。使用及結果情況與indexOf相似。
例如,同樣是想查尋“孫悟空打敗了假孫悟空”這個字符串中,“空”最后一次的位置:
String str = "孫悟空打敗了假孫悟空";
int index1 = str.lastIndexOf("空");//結果為9
int index2 = str.lastIndexOf("空", 4);//結果為2,限定了搜索的范圍是在0與4之間
總結:以上4個方法都是查找位置,如果沒有找到相應的字符串,均是返回-1,一個很常用的用法為:將是否存在做為判斷的條件,例如:
String str = "孫悟空";
//如果"孫悟空"這個字符串中含有"孫"這個字符串的話
//if是判斷語句,將在下面進行講解
if(str.indexOf("孫") != -1){
//TODO:執行代碼
}
? int length():返回此字符串的長度
例如:
String str = "孫悟空";
System.out.println(str.length());//結果為3
由此可見,每個字符串的可用位置標號都是從0到(字符串.length()-1)。
? String replaceFirst(String regex, String replacement):該方法用字符串replacement的內容替換當前字符串中遇到的第一個和字符串regex相一致的子串,并將產生的新字符串返回。
例如:
String str = "孫悟空打敗了假孫悟空";
System.out.println(str.replaceFirst("孫悟空","孫行者"));
//結果為:孫行者打敗了假孫悟空
? String replaceAll(String regex, String replacement) :該方法用字符串replacement的內容替換當前字符串中遇到的所有和字符串regex相一致的子串,并將產生的新字符串返回
例如:
String str = "孫悟空打敗了假孫悟空";
System.out.println(str.replaceAll("孫悟空","孫行者"));
//結果為:孫行者打敗了假孫行者
? String[] split(String regex):根據給定的字符串來拆分此字符串,得到一個字符串數組, String[]是元素為字符串的數組,我們將在下面講解
例如上例中的那個字符串:
String str = "孫悟空打敗了假孫悟空";
String[] childs = str.split("打敗了");
通過split方法,我們將得到一個長度為2的字符串數組,里面有2個Spring元素,分別為"孫悟空"和"假孫悟空"。
這個只是舉例說明,在真實的程序編寫中,最多的用法是將關聯的數據以一定的特殊符號間隔開,便于整體存儲,比如,西游團隊的四個人,就可以存儲在一起,用逗號分隔:
String str = "唐僧,孫悟空,豬八戒,沙僧";
String[] childs = str.split(",");
這樣得到的childs這個數組中就會有4個Spring元素,分別為"唐僧"、"孫悟空"、"豬八戒"和"沙僧"。
? boolean startsWith(String prefix):測試此字符串是否以指定的前綴開始,常用于條件判斷
例如:
String str = "孫悟空";
if(str.startsWith("孫")){
//TODO:如果str這個字符串是以"孫"開頭的,那么執行以下代碼
}else{
//TODO:如果str這個字符串不是以"孫"開頭的,那么執行以下代碼
}
String str = "孫悟空";
if(str.startsWith("孫")){
//TODO:如果str這個字符串是以"孫"開頭的,那么執行以下代碼
}else{
//TODO:如果str這個字符串不是以"孫"開頭的,那么執行以下代碼
}
? String substring(int beginIndex):返回一個新的字符串,它是此字符串的一個子字符串
? String substring(int beginIndex, int endIndex):返回一個新字符串,它是此字符串的一個子字符串
以上兩個方法同樣是String中的兩個重載的方法,如果指定了beginIndex和endIndex,那么就返回這兩個位置標號中間的字符串,如果只指定了beginIndex,那么就返回從beginIndex這個位置標號到整個字符串結尾的字符串。
例如:
String str = "孫悟空打敗了假孫悟空";
System.out.println(str.substring (3));//結果為:"打敗了假孫悟空"
System.out.println(str.substring (3, 5));//結果為:"打敗"
? String toLowerCase():把字符串轉換為小寫
? String toUpperCase():把字符串轉換為大寫
以上兩個方法主要針對于英文組成的字符串。
例如:
String str = "WoShiSunWukong";
System.out.println(str.toLowerCase());//結果為:"woshisunwukong"
System.out.println(str.toUpperCase());//結果為:"WOSHISUNWUKONG"
? String trim():去掉字符串兩端的空格。此方法可以去掉該字符串首尾的空格、制表符等,一般用于驗證用戶名、密碼輸入框。
例如:
String str = " 孫悟 空 ";
System.out.println(str.trim());//結果為:"孫悟 空"
此方法只會去除兩端的空格,不會去除中間夾著的空格。如果想去除包含中間的全部空格,那么就要用之前講過的replaceAll方法:
String str = " 孫悟 空 ";
System.out.println(str.replaceAll(" ", ""));//結果為:"孫悟空"
? static String valueOf(XXX b):把其他類型變量轉成字符串
任意類型的數據都可以通過這個方法轉成字符串,其他類型的好理解,那么布爾型數據會轉成什么呢?答案是"true"或者"false"。
例如:
boolean b = false;
System.out.println(String.valueOf(b));//結果為:"false"
上面的方法會在我們編程中大量使用,因此,務必要熟練掌握和使用。
4.3 空字符串與NULL
上面講過,所有的引用類型,如果不指定初始值的話,默認都是null。Java中,null是一個關鍵字,用來標識一個不確定的對象,或者說是一個不存在的對象。可以將null賦給引用類型變量,但不可以將null賦給基本類型變量。
null本身雖然能代表一個不確定的對象,但就null本身來說,它不是對象,也不知道什么類型,也不是java.lang.Object的實例(所有的對象都是java.lang.Object的子類,在下面講到繼承的時候會講解)。如果一個引用類型不被初始化,那么它就是沒有分配內存沒有內存地址,是不存在且不可用的,用null只是來標識這種情況。另外,null還有一個作用就是通知JVM釋放內存,讓一個非null的引用類型變量指向null,這樣這個對象就不再被任何對象應用了,等待JVM垃圾回收機制去回收。
如果一個String類型的數據沒有初始化,那么它的值也是null,是不是就是等于""呢?
答案是否定的。null代表聲明了一個空對象,根本就不是一個字符串。而""代表聲明了一個對象實例,這個對象實例的值是一個長度為0的空字符串。null代表聲明了一個空對象,對空對象做任何操作都不行的,除了=和==,而且也不能調用String類的方法,而""則是一個字符串,只是這個字符串里面沒有內容,但是任何字符串的操作都是可以用的,而且可以調用String類的全部方法。
可以這樣理解:
String s=""; 是你沒說任何話
String s = null; 是你根本就沒法說話
或者說,""是空氣,而null則是真空。
4.4 變長的字符串--StringBuffer類
與String類不同,StringBuffer類是一個在操作中可以更改其內容的字符串類。一旦創建StringBuffer類的對象,在操作中可以更改和變動字符串的內容。也就是說對于StringBuffer類的對象不僅能進行查找和比較等操作,也可以做添加、插入、修改之類的操作。
StringBuffer相當于是我們一開始不確定我們的字符串是什么樣子的,有多少字符,因此我們先定義一塊區域,然后再往里插入和添加,最后插入完了,再統一生成出一個字符串,最常用的添加方法就是append()。
大家看一下這兩段代碼:
String s1 = "我是" + "孫悟空" + ",今年" + String.valusOf(1226) + "歲";
String s2 = new StringBuffer().append("我是").append("孫悟空").append(",今年").append(1226).append("歲").toString();
這兩句代碼執行完成后的效果是一樣的,那么除了寫法上簡單整齊一些之外,還有什么不同呢?
String的值是不可變的,這就導致每次對String的操作都會生成新的String對象,不僅效率低下,而且大量浪費有限的內存空間。而StringBuffer是可變類,和線程安全的字符串操作類,任何對它指向的字符串的操作都不會產生新的對象。 每個StringBuffer對象都有一定的緩沖區容量,當字符串大小沒有超過容量時,不會分配新的容量,當字符串大小超過容量時,會自動增加容量。
StringBuffer類提供了多種構造方法來創建類StringBuffer的對象:
public StringBuffer():創建一個空字符串緩沖區,默認初始長度為16個字符。
public StringBuffer(int length):length指定的初始長度創建一個空字符串緩沖區
public StringBuffer(String str):用指定的字符串str創建一個字符串緩沖區,其長度為str的長度再加16個字符。
10個重載的append方法,參數分別是不同的數據類型,可以在字符串緩沖區末尾追加boolean、char、字符數組、double、float、int、long、string、Object等類型的新內容,append方法的返回類型均為StringBuffer。
9個重載的insert方法,參數分別是不同的數據類型,可以在字符串緩沖區中指定位置處插入char 、字符數組、double、float、int、long、boolean、string、Object等類型的新內容。insert方法的返回類型均為StringBuffer。
在稍后的例子學習中,會逐步的用到這些類與方法,爭取越來越熟練。
4.5大數據處理(超大的整數和浮點數)
Java里面整型int與浮點型float,double它們存放數據的范圍是有邊界的。那么如果需要更大的數據時,這些數據類型肯定是滿足不了這種需求,所以就用到了BigInteger(超大的整數)和BigDecimal(超大的浮點數)這兩個類來解決這個問題。這兩個都不是基本類型,而是類,因此同樣屬于引用類型。
例如,我們想定義孫悟空身上有多少根毛,這個絕對是超過了long型的最大范圍了,那么我們就可以定義為BigInteger :
BigIntegerallHair; //未設置初始值,因為我也不知道多少根
這兩個類的對象能表示最大范圍不清楚,理論上能夠表示無限大的數,只要計算機內存足夠大。這兩個類都在java.math.*包中,因此想使用的話,必須在類開頭處引用該包。這里暫時可以先記住,將在“引入工具包”章節中進行詳細講解,引入了之后,就可以像String一樣來調用方法來使用了。
由于它不屬于基本類型,因此運算不能使用“+”、“-”、“*”、“/”等運算符號,而是用方法來完成。下面我們通過兩個例子來說明如何使用這兩個類:
BigInteger:
//引入工具包,在后面講解
import java.math.*;
public class BigIntegerTest {
public static void main(String[] args) {
//BigInteger類型的常量
BigInteger A = BigInteger.ONE;
System.out.println("BigInteger.ONE的結果為 " + A);//1
BigInteger B = BigInteger.TEN;
System.out.println("BigInteger.TEN的結果為 " + B);//10
BigInteger C = BigInteger.ZERO;
System.out.println("BigInteger.ZERO的結果為 " + C);//0
//初始化
BigInteger c = new BigInteger("12345670",8);//c = 12345670 八進制
System.out.println(c);//2739128
BigInteger d = BigInteger.valueOf(100);//d = 100
BigInteger e = new BigInteger(newbyte[]{1,0});//00000001 00000000
System.out.println(e);//256
System.out.println(e.bitCount());
System.out.println(e.bitLength());
//運算
BigInteger a = BigInteger.valueOf(1005550);
BigInteger b = BigInteger.valueOf(1044000);
BigInteger c1 = a.add(b); // 大數加法
System.out.println("加的結果為 " + c1);
BigInteger c2 = a.subtract(b); // 大數減法
System.out.println("減的結果為 " + c2);
BigInteger c3 = a.multiply(b); // 大數乘法
System.out.println("乘的結果為 " + c3);
BigInteger c4 = a.divide(b); // 大數除法
System.out.println("除的結果為 " + c4);
BigInteger c5 = a.mod(b);
System.out.println("模的結果為 " + c5);
BigInteger cc5 = a.remainder(b);
System.out.println("余的結果為 " + cc5);
BigInteger c6 = a.max(b);// 取最大
System.out.println("最大為 " + c6);
BigInteger c7 = a.min(b); // 取最小
System.out.println("最小為 " + c7);
BigInteger c8 = a.pow(10); //指數運算
System.out.println("指數運算結果為" + c8);
if (a.equals(b)) // 判斷是否相等
System.out.println("相等");
else
System.out.println("不相等");
BigInteger c10 = a.abs(); // 求絕對值
System.out.println("a的絕對值為 " + c10);
BigInteger c11 = a.negate(); // 求相反數
System.out.println("a的相反數為 " + c11);
}
}
輸出結果為:
BigInteger.ONE的結果為 1
BigInteger.TEN的結果為 10
BigInteger.ZERO的結果為 0
2739128
256
1
9
加的結果為 2049550
減的結果為 -38450
乘的結果為 1049794200000
除的結果為 0
模的結果為 1005550
余的結果為 1005550
最大為 1044000
最小為 1005550
指數運算結果為1056906827544881411951404077372867677711484472656250000000000
不相等
a的絕對值為 1005550
a的相反數為 -1005550
BigDecimal:
//引入工具包,在后面講解
import java.math.*;
public class BigDecimalTest {
public static void main(String[] args) {
//BigDecimal類型的常量
BigDecimal A = BigDecimal.ONE;
System.out.println("BigDecimal.ONE的結果為 " + A);//1
BigDecimal B = BigDecimal.TEN;
System.out.println("BigDecimal.TEN的結果為 " + B);//10
BigDecimal C = BigDecimal.ZERO;
System.out.println("BigDecimal.ZERO的結果為 " + C);//0
//初始化
BigDecimal a = new BigDecimal("89.12345678987654321");
BigDecimal b = new BigDecimal("1000");
BigDecimal e = new BigDecimal(newchar[]{'2','1','.','2'});
System.out.println(e);//21.2
//運算
BigDecimal a = new BigDecimal("89.1234");
BigDecimal b = new BigDecimal("1000.36728834");
BigDecimal c1 = a.add(b); // 大數加法
System.out.println("加的結果為 " + c1);
BigDecimal c2 = a.subtract(b); // 大數減法
System.out.println("減的結果為 " + c2);
BigDecimal c3 = a.multiply(b); // 大數乘法
System.out.println("乘的結果為 " + c3);
//注意,這里如果不能除盡,就會拋出一個ArithmeticException錯誤
BigDecimal c4 = a.divide(b); // 大數除法
System.out.println("除的結果為 " + c4);
BigDecimal cc5 = a.remainder(b);
System.out.println("余的結果為 " + cc5);
BigDecimal c6 = a.max(b);// 取最大
System.out.println("最大為 " + c6);
BigDecimal c7 = a.min(b); // 取最小
System.out.println("最小為 " + c7);
BigDecimal c8 = a.pow(10); //指數運算
System.out.println("指數運算結果為" + c8);
if (a.equals(b)) // 判斷是否相等
System.out.println("相等");
else
System.out.println("不相等");
BigDecimal c10 = a.abs(); // 求絕對值
System.out.println("a的絕對值為 " + c10);
BigDecimal c11 = a.negate(); // 求相反數
System.out.println("a的相反數為 " + c11);
}
}
輸出結果為:
BigDecimal.ONE的結果為 1
BigDecimal.TEN的結果為 10
BigDecimal.ZERO的結果為 0
21.2
加的結果為 1089.12345678987654321
減的結果為 -910.87654321012345679
乘的結果為 89123.45678987654321000
除的結果為 0.08912345678987654321
余的結果為 89.12345678987654321
最大為 1000
最小為 89.12345678987654321
指數運算結果為31616968703194087333.71474887174406077078834132429726194300860779253381797884337048064650178740361301799617209955812260340316817120048633156996017759816867243104420462962178656466746940511201
不相等
a的絕對值為 89.12345678987654321
a的相反數為 -89.12345678987654321
說明一下:
//創建BigDecimal對象
BigDecimal bigNumber = new BigDecimal("89.1234567890123456789");
BigDecimal bigRate = new BigDecimal(1000);
BigDecimal bigResult = new BigDecimal(); //對象bigResult的值為0.0
注意,BigDecimal中的divide函數和BigInteger中的稍有不同。
方法1:
pubilc BigDecimal divide(BigDecimal divisor)
API中的解釋: 返回一個 BigDecimal,其值為 (this / divisor),其首選標度為 (this.scale() - divisor.scale());如果無法表示準確的商值(因為它有無窮的十進制擴展),則拋出 ArithmeticException。
方法2:
pubilc BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
scale指的是小數點后的位數。比如123.456則scale就是3,是BigDecimal類中的方法啊。
比如:BigDecimal b = new BigDecimal("123.456");//b.scale(),返回的就是3.
roundingMode是小數的保留模式。它們都是BigDecimal中的常量字段。
比如:BigDecimal.ROUND_HALF_UP表示的就是4舍5入。
pubilc BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
它的意思是說:我用一個BigDecimal對象除以divisor后的結果,并且要求這個結果保留有scale個小數位,roundingMode表示的就是保留模式,是四舍五入啊還是其它的,你可以自己選!
通過上面兩個例子,我們應該了解了對于超大數據的運算處理方式,像很多銀行或者證券類的功能中,我們會大量用到這兩個類。對于不熟悉的類,大家應該養成查看API的好習慣,上面會包含可用的常量、屬性及方法。
4.6其他類的對象做屬性
前面說地,對象可以通過“.”運算符來調用自己的屬性和方法。因此,如果類中的一個屬性是另一個類的對象,那么就要以通過這個對象,來調用另一個類中的方法,這個原理其實與String是相同的。
例如:“孫悟空”類中的一個屬性是:金箍棒類 手上拿的東西;
那么,就可以通過這個對象,來調用“金箍棒”類中的方法:手上拿的東西.擊打();
這個也是Java屬性的一個精髓所在,通過這樣就可以將各個對象關聯起來,形容更復雜的關系,也就可以實現更復雜的功能。
把上面講到的類型定義,以及類與變量起名規則,放到“孫悟空”類的定義中使其豐富一下,就可以這樣寫:
4.7 數組
什么是數組?
數組就是一個長度固定的數據結構,它存儲多個相同類型的元素(或數值)。比如,西游團隊就是一個數組,里面的元素都是人;孫悟空從蟠桃會上拿回來的裝桃子的麻袋也是一個數組,里面的元素都是桃子。
前面我們講過,一切皆對象,因此,數組也是一個對象。
數組的下標都是從0開始的,這一點和我們自然的認識些不同。為什么不是從1開始呢?是因為數組下標實際上是偏移量。數組元素位置的計算是以首個元素(地址)為基準,以偏移個數乘以元素所占空間大小來計算,這個偏移量就是數組個下標數,首個元素相對于自己是偏移了0個,所以數組的下標起始從0開始。
在Java中,數組可以是任何類型的──原始類型或類類型,也就是說,數組元素可以是原始類型的量,也可以是某一個類的對象。比如,“孫悟空”類中,可以有一個屬性,叫做:出生地坐標,這個是一個元素為基本類型(數字)的數組;還可以有一個屬性,叫做:所管理的猴子猴孫,這個屬性的類型就是一個元素為“猴”類的數組。
根據數組類型,一般分為簡單類型數組(數組的元素為8種基本類型)和復雜類型數組(數組元素為其它類)
簡單類型數組在用new運算符建立時既分配了內存空間又賦上了初始默認值
復雜類型數組建立之后每個元素都是空值
數組的創建一般需要以下三個步驟:
l 數組的聲明
數組元素類型 數組名[ ];
例: float 出生地坐標[];
猴 所管理的猴子猴孫[];
l 創建數組空間
創建是給數組分配內存空間,它可以直接使用new運算符,也可以直接用枚舉來創建。格式如下:
數組名 = new 數組元素類型[數組長度];
例如:
出生地坐標= new float[2]; //經度、緯度
所管理的猴子猴孫= new 猴[20000];
創建數組空間的工作可以和聲明數組的工作組合在一起用一條語句來實現。
float出生地坐標[]; 出生地坐標= new float[2];
等價于:
float出生地坐標[]= new float[2];
或者使用枚舉創建數組:
float出生地坐標[] = { 126, -63 };
l 初始化數組
數組中的各元素是有先后次序的,每個數組元素用數組的名字和它在數組中的位置來表達。
在上一節創建的數組“所管理的猴子猴孫”中,所管理的猴子猴孫[0]表示數組“所管理的猴子猴孫”中的第一個元素,所管理的猴子猴孫[1]表示數組“所管理的猴子猴孫”中的第二個元素,依次類推,數組中的最后一個元素為所管理的猴子猴孫[19999]
初始化數組就是要使數組中的各個元素有確定的數值,如用枚舉法定義的數組就不需要初始化了。而用new運算符定義的數組則需要根據實際情況賦值。
如果數組元素的類型是基本數據類型,由于基本數據類型都有缺省值,數組元素都自動初始化為缺省值。
對于以某個類的對象為數組元素的數組,初始化每個數組元素是必須的。
所有的數組都有一個屬性length,這個屬性存儲了數組元素的個數。注意檢查數組下標是否越界
數組都可以用循環的方式來賦值以及遍歷取值,這個方式將在講到循環結構的時候再進行講解。
命令行參數
記得這個老熟人吧,從我們一開始的時候就接觸過它,這個就是一個數組。我們來重溫一下,溫故而知新。
每個Java應用程序都有一個帶String[] arg參數的main方法,該方法將可以接收一個字符串數組作為命令行參數:
public static void main(String[] args)
args[0] ->第一個參數(程序名不存儲在args數組中)
args[1] ->第二個參數
…
args.length ->參數個數
例如:執行“java Message –xitian 唐僧 SunWukong”,則
args[0]:“-xitian”
args[1]:“唐僧”
args[2]:“SunWukong”
數組類的使用
在“java.util”包中,提供一個數組類Arrays,該類提供了一些方法用于排序、查找等操作,在編寫程序中可以直接使用這些方法。這個工具的使用與之前的大數據據類型一樣,也需要引入相應的工具包:
import java.util.Arrays;
4.7.1 轉換成字符串
為什么之前說字符串是程序中最主要的部分,就是因為字符串是在生活中最常用理解與使用的一個格式。雖然為了程序編寫方便而構造出了很多其他的數據類型,但是在很多情況下我們仍然是需要將其轉換成字符串格式。很多數據格式也都提供了與字符串之間方便的轉換方法,數組也不例外。
對于簡單類型的一維數組,可以使用如下方法:
public static String toString(Xxx[] a)
返回包含a中數據元素的字符串,這些數據元素被放在括號內,并用逗號分隔;
參數a類型為int、long、short、char、byte、boolean、float或double數組。
對于類型是對象的一維數組或多維數組,需要使用下面這個方法:
public static String deepToString(Xxx[] a)
public static String deepToString(Xxx[][] a)
這些方法將在下面的例子使用。
4.7.2 排序
? 直接使用sort方法,來對數組做升序排序。sort方法常見的使用形式如下:
public static void sort(Xxx a[])
int a[] = new int[20];
Arrays.sort(a)
? 該方法用改進的快速排序方法對指定的數組a進行排序,其中數組a是類型為char、byte、short、int、long、float、double或者boolean的一個數組。
? sort方法還有另外一種常見的形式:
public static void sort(Xxx a[],int fromIndex,int toIndex)
? 這種形式只對數組a中指定范圍內的元素(從a[fromIndex]到a[toIndex]之間的元素,其中不包含a[toIndex])排序。例:為整型數組排序
4.7.3 查找
public static int binarySearch(Xxx a[],Xxx v);
int a[] = new int[20];
Arrays.binarySearch(a, 10)
? 該方法用折半查找算法(關于算法,會在后續的課程里再介紹)在指定的數組a查找值為v的元素。其中數組a是類型為char、byte、short、int、long、float、double或者boolean的一個數組,v是與數組a的元素類型相同的值
? 該方法如果在數組a查找到值為v的元素,則返回該元素的下標;如果沒有找到匹配的元素,則返回一個負值r,位置-(r+1)為保持數組有序時值為v的元素應該插入的位置
4.7.4 填充
public static void fill(Xxx a[],Xxx v)
int a[] = new int[20];
Arrays.fill(a, 1)
? 該方法用指定的值v來填充數組a,執行該方法的結果是:
? 數組a中所有元素的值都變成v
? 其中數組a是類型為char、byte、short、int、long、float、double或者boolean的一個數組。
4.7.5 復制
數組的復制一共有兩種方法,分別是Arrays.copyOf以及System.arraycopy。
第一種復制的語法有如下兩種方式:
public static Xxx[]copyOf(Xxx[] a,int length)
public static Xxx[]copyOf(Xxx[] a,int start,int end)
int a[] = new int[20];
int b[] = Arrays.copyOf(a, 5, 10)
返回與a類型相同的一個數組,其長度為length或者end-start,數組元素為a的值。
Xxx代表類型:int、long、short、char、boolean、float等
start:起始下標(包含這個值)
end: 終止下標(不包含這個值),這個值可能大于a.length,這種情況下結果為0或false
length:拷貝的數據元素長度,如果length大于a.length結果為0或false;否則數組中只有前面length個數據元素的拷貝值;
這里要注意,目標數組必須在調用arraycopy之前分配內存。如果長度大于原始數組的長度,那么多出來的元素將被賦上默認值,數組元素是數值型,那么多余元素將被賦值為0;數組元素是布爾型,則多余元素被賦值為false等等。相反如果長度小于原始數組的長度,則只拷貝原始數組最前面的數據元素。
例如:
int[] old1={1,2,3,4};
int[] old2={11,22,33,44,55};
//需要在程序頂部import java.util.Arrays;
old2=Arrays.copyOf(old1,old2.length);
System.out.println(Arrays.toString(old2));
輸出:[1, 2, 3, 4, 0]
第二種方法的語法如下:
java.lang.System.arraycopy(from,fromIndex,to,toIndex,count)
該方法從數組from的索引fromIndex位置起,復制count個元素到數組to的從索引toIndex位置開始的地方。
from:任意類型數組
formIndex:原始數組from中待拷貝元素的起始下標
to:與from同類型的數組
toIndex:目標數組to放置拷貝元素的起始下標
count:拷貝的元素數量
這里要注意,目標數組必須在調用arraycopy之前分配內存。必須保證數組to的長度大于或等于數組from的長度,否則會報錯。
例如:
int[] old1={1,2,3,4};
int[] old2={11,22,33,44,55};
System.arraycopy(old1,1,old2,0,3); System.out.println(Arrays.toString(old2));
輸出:[2, 3, 4, 44, 55]
4.7.6 多維數組的使用
什么是多維數組?就是一個數組,里面的元素依然是數組。
舉個例子吧,王母娘娘瑤池開蟠桃會,擺放幾排桌椅,每排桌椅上都坐滿了神仙。這個蟠桃會就是一個數組,數組里的元素是一排桌椅。而每一排桌椅又是一個數組,里面的元素是每一位神仙。
二維數組的定義語法如下:
數組元素類型 數組名[][] = new 數組元素類型[數組長度][];
例如:
//假設有12排桌椅,每排坐著12個神仙
ShenXian[][] panTaoHui = new ShenXian[12][12];
//依次類推,我們還定義三維數組,甚至更多維的數組
ShenXian[][][] panTaoHui = new ShenXian[12][12][12];
//這里我們可以看出,整個二維數組的標識類型,就是最底層元素的類型,因為其他上層的元素類型都是“數組”,不需要顯式標識
//以上是針對對象的多維數組,為了方便我們理解,在實際編程中更常用的基礎類型的多維數組,比如:
int a[][] = new int[10][5]
多維數組也可以使用枚舉定義,同時完成了初始化的工作,例如:
ShenXian [][] panTaoHui =
{
{ new ShenXian("如來佛祖"), new ShenXian("觀音菩薩")……},
{ new ShenXian("太上老君"), new ShenXian("太上老君")……},
{new ShenXian("赤腳大仙"), new ShenXian("太白金星")……}
}
或者:
int[][] a =
{
{1,2,3},
{4,5,6},
{7,8,9}
}
大家可以發現,任何級別的數組元素都是以逗號分隔,并且最后一個元素后面沒有逗號,這個要記好。
訪問二維數組的元素與一維數組類似,也是利用下標,即:
數組名[一維下標][二維下標]
例如PanTaoHui[0][1] 即為觀音菩薩。
a[0][1] 即為2。
切記,每一層數組的下標都是從0開始,切記!
想快速打印一個二維數組的元素列表,可以調用:
System.out.println(Arrays.deepToString(數組名));
例如:System.out.println(Arrays.deepToString(a)),輸出的就是[{1,2,3},{4,5,6},{7,8,9}]
4.7.7 不規則數組
上面前的都是規則的數組,那么什么是不規則的數組呢?
孫悟空大鬧蟠桃會之后,想到花果山的孩兒們都沒有吃過這么好的桃子呢,于是他找了幾個麻袋,將桌上的桃子全都裝了回去。我們假設他裝了三個麻袋,但是每個麻袋里的桃子他可沒有數過,應該不可能是相同的數量。
因此,我們可以這樣理解,最底層的數組長度不相同的多維數組,即是不規則數組。換句話說,不規則數組就是不整齊的多維數組
Java中并沒有針對多維數組的定義,這也造就了它在數組方面的優勢:Java實際上只有一維數組,而數組的元素可以是任意長度的數組,因此我們可以通過這個特性來很方便的定義多維數組,以及不規則數組。
比如上例就可以寫成:
Taozi [][] madai= new Taozi[3][];//3個麻袋
madai[0] = new Taozi[300];
madai[1] = new Taozi[600];
madai[2] = new Taozi[900];
最后再補充一點,多維數組(包括不規則數組),同樣可以用循環來賦值和遍歷。循環這里將在下面來詳細講解。
總結
以上是生活随笔為你收集整理的mybatisplus修改单个属性_第二节官封弼马温——类的属性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 应用程序窗口hwnd初始化_Golang
- 下一篇: traceroute程序_来!程序猿教你