一美旧、 包裝類
(1)包裝類概述
Java是面向對象的語言穷躁,但并不是“純面向對象”的祠挫,因為我們經常用到的基本數據類型就不是對象典奉。但是我們在實際應用中經常需要將基本數據轉化成對象,以便于操作鳞芙。比如:將基本數據類型存儲到Object[]數組或集合中的操作等等眷柔。
為了解決這個不足,Java在設計類時為每個基本數據類型設計了一個對應的類進行代表原朝,這樣八個和基本數據類型對應的類統(tǒng)稱為包裝類(Wrapper Class)驯嘱。
在這八個類中,除了Character和Boolean以外喳坠,其他的都是“數字型”鞠评,“數字型”都是java.lang.Number的子類。Number類是抽象類壕鹉,因此它的抽象方法剃幌,所有子類都需要提供實現(xiàn)。Number類提供了抽象方法:intValue()晾浴、longValue()锥忿、floatValue()、doubleValue()怠肋,意味著所有的“數字型”包裝類都可以互相轉型敬鬓。
(2)自動裝箱和拆箱
自動裝箱和拆箱就是將基本數據類型和包裝類之間進行自動的互相轉換。JDK1.5后,Java引入了自動裝箱(autoboxing)/拆箱(unboxing)钉答。
-
自動裝箱
基本類型的數據處于需要對象的環(huán)境中時础芍,會自動轉為“對象”。以Integer為例:JDK1.5以后数尿,Java提供了自動裝箱的功能仑性,因此只需Integer i = 5這樣的語句就能實現(xiàn)基本數據類型轉換成包裝類,這是因為JVM為我們執(zhí)行了Integer i = Integer.valueOf(5)這樣的操作右蹦,這就是Java的自動裝箱诊杆。
Integer i = 100;//自動裝箱
//相當于編譯器自動為您作以下的語法編譯:
Integer i = Integer.valueOf(100);//調用的是valueOf(100),而不是new Integer(100)
-
自動拆箱
每當需要一個值時何陆,對象會自動轉成基本數據類型晨汹,沒必要再去顯式調用intValue()、doubleValue()等轉型方法贷盲。如 Integer i = 5;int j = i; 這樣的過程就是自動拆箱淘这。
Integer i = 100;
int j = i;//自動拆箱
//相當于編譯器自動為您作以下的語法編譯:
int j = i.intValue();
-
總結
自動裝箱過程是通過調用包裝類的valueOf()方法實現(xiàn)的,而自動拆箱過程是通過調用包裝類的 xxxValue()方法實現(xiàn)的(xxx代表對應的基本數據類型巩剖,如intValue()铝穷、doubleValue()等)。
整型佳魔、char類型所對應的包裝類曙聂,在自動裝箱時,對于-128~127之間的值會進行緩存處理鞠鲜,其目的是提高效率筹陵。
(3)包裝類的緩存問題
緩存處理的原理為:如果數據在-128~127這個區(qū)間,那么在類加載時就已經為該區(qū)間的每個數值創(chuàng)建了對象镊尺,并將這256個對象存放到一個名為cache的數組中。每當自動裝箱過程發(fā)生時(或者手動調用valueOf()時)并思,就會先判斷數據是否在該區(qū)間庐氮,如果在則直接獲取數組中對應的包裝類對象的引用,如果不在該區(qū)間宋彼,則會通過new調用包裝類的構造方法來創(chuàng)建對象弄砍。
public class Test3 {
public static void main(String[] args) {
Integer in1 = -128;
Integer in2 = -128;
System.out.println(in1 == in2);//true 因為123在緩存范圍內
System.out.println(in1.equals(in2));//true
Integer in3 = 1234;
Integer in4 = 1234;
System.out.println(in3 == in4);//false 因為1234不在緩存范圍內
System.out.println(in3.equals(in4));//true
}
}
二、 String類
(1)String
String 類對象代表不可變的Unicode字符序列输涕,因此我們可以將String對象稱為“不可變對象”音婶。 那什么叫做“不可變對象”呢?指的是對象內部的成員變量的值無法再改變。
substring()是對字符串的截取操作莱坎,但本質是讀取原字符串內容生成了新的字符串
public class TestString1 {
public static void main(String[] args) {
String s1 = new String("abcdef");
String s2 = s1.substring(2, 4);
// 打右率健:ab199863
System.out.println(Integer.toHexString(s1.hashCode()));
// 打印:c61, 顯然s1和s2不是同一個對象
System.out.println(Integer.toHexString(s2.hashCode()));
}
}
在遇到字符串常量之間的拼接時,編譯器會做出優(yōu)化碴卧,即在編譯期間就會完成字符串的拼接弱卡。因此,在使用==進行String對象之間的比較時住册,我們需要特別注意
public class TestString2 {
public static void main(String[] args) {
//編譯器做了優(yōu)化,直接在編譯的時候將字符串進行拼接
String str1 = "hello" + " java";//相當于str1 = "hello java";
String str2 = "hello java";
System.out.println(str1 == str2);//true
String str3 = "hello";
String str4 = " java";
//編譯的時候不知道變量中存儲的是什么,所以沒辦法在編譯的時候優(yōu)化
String str5 = str3 + str4;
System.out.println(str2 == str5);//false
}
}
String類常用的方法有:
1.String類的下述方法能創(chuàng)建并返回一個新的String對象: concat()婶博、 replace()、substring()荧飞、 toLowerCase()凡人、 toUpperCase()、trim()叹阔。
2.提供查找功能的有關方法: endsWith()挠轴、 startsWith()、 indexOf()条获、lastIndexOf()忠荞。
3.提供比較功能的方法: equals()、equalsIgnoreCase()帅掘、compareTo()委煤。
4.其它方法: charAt() 、length()修档。
(2)StringBuffer和StringBuilder
StringBuffer和StringBuilder非常類似碧绞,均代表可變的字符序列。 這兩個類都是抽象類AbstractStringBuilder的子類吱窝,方法幾乎一模一樣讥邻。StringBuilder和StringBuffer稱之為“可變字符序列”。那兩者有什么區(qū)別呢?
1.StringBuffer JDK1.0版本提供的類院峡,線程安全兴使,做線程同步檢查, 效率較低照激。
2.StringBuilder JDK1.5版本提供的類发魄,線程不安全,不做線程同步檢查俩垃,因此效率較高励幼。 建議采用該類。
-
常用方法列表:
1.重載的 public StringBuilder append()
可以為該StringBuilder 對象添加字符序列口柳,仍然返回自身對象苹粟。
2.public StringBuilder delete(int start,int end)
可以刪除從start開始到end-1為止的一段字符序列,仍然返回自身對象跃闹。
3.public StringBuilder deleteCharAt(int index)
移除此序列指定位置上的 char嵌削,仍然返回自身對象毛好。
4.重載的 public StringBuilder insert(…)
可以為該StringBuilder 對象在指定位置插入字符序列,仍然返回自身對象掷贾。
5.public StringBuilder reverse()
用于將字符序列逆序睛榄,仍然返回自身對象。
6. public String toString()
7. 和 String 類含義類似的方法:
public int indexOf(String str)
public int indexOf(String str,int fromIndex)
public String substring(int start)
public String substring(int start,int end)
public int length()
char charAt(int index)
(3) String使用的陷阱
String一經初始化后想帅,就不會再改變其內容了场靴。對String字符串的操作實際上是對其副本(原始拷貝)的操作,原來的字符串一點都沒有改變港准。比如:String s ="a"; 創(chuàng)建了一個字符串旨剥,s = s+"b"
實際上原來的"a"字符串對象已經丟棄了,現(xiàn)在又產生了另一個字符串s+"b"(也就是"ab")
如果多次執(zhí)行這些改變串內容的操作浅缸,會導致大量副本字符串對象存留在內存中轨帜,降低效率。如果這樣的操作放到循環(huán)中衩椒,會極大影響程序的時間和空間性能蚌父,甚至會造成服務器的崩潰。
相反毛萌,StringBuilder和StringBuffer類是對原字符串本身操作的苟弛,可以對字符串進行修改而不產生副本拷貝或者產生少量的副本。因此可以在循環(huán)中使用阁将。
public class Test {
public static void main(String[] args) {
/**使用String進行字符串的拼接*/
String str8 = "";
//本質上使用StringBuilder拼接, 但是每次循環(huán)都會生成一個StringBuilder對象
long num1 = Runtime.getRuntime().freeMemory();//獲取系統(tǒng)剩余內存空間
long time1 = System.currentTimeMillis();//獲取系統(tǒng)的當前時間
for (int i = 0; i < 5000; i++) {
str8 = str8 + i;//相當于產生了10000個對象
}
long num2 = Runtime.getRuntime().freeMemory();
long time2 = System.currentTimeMillis();
System.out.println("String占用內存 : " + (num1 - num2));
System.out.println("String占用時間 : " + (time2 - time1));
/**使用StringBuilder進行字符串的拼接*/
StringBuilder sb1 = new StringBuilder("");
long num3 = Runtime.getRuntime().freeMemory();
long time3 = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
sb1.append(i);
}
long num4 = Runtime.getRuntime().freeMemory();
long time4 = System.currentTimeMillis();
System.out.println("StringBuilder占用內存 : " + (num3 - num4));
System.out.println("StringBuilder占用時間 : " + (time4 - time3));
}
}
(4) Java字符串格式化
三膏秫、 時間處理相關類
在計算機世界,我們把1970 年 1 月 1 日 00:00:00定為基準時間做盅,每個度量單位是毫秒(1秒的千分之一)缤削。我們用long類型的變量來表示時間,從基準時間往前幾億年吹榴,往后幾億年都能表示亭敢。如果想獲得現(xiàn)在時刻的“時刻數值”,可以使用:long now = System.currentTimeMillis();
(1)Date時間類(java.util.Date)
public class TestDate {
public static void main(String[] args) {
Date date1 = new Date();
System.out.println(date1.toString()); //Tue Jan 14 21:12:39 CST 2020
long i = date1.getTime();
Date date2 = new Date(i - 1000);
Date date3 = new Date(i + 1000);
System.out.println(date1.after(date2));//true 測試此日期是否在指定日期之后
System.out.println(date1.before(date2));//false 測試此日期是否在指定日期之前图筹。
System.out.println(date1.equals(date2));//false 比較兩個日期的相等性帅刀。
System.out.println(date1.before(date3));//true
System.out.println(date1.after(date3));//false
System.out.println(date1.equals(date3));//false
System.out.println(new Date(1000L * 60 * 60 * 24 * 365 * 39L).toString());//Mon Dec 22 08:00:00 CST 2008
}
}
(2)DateFormat類和SimpleDateFormat類
-
DateFormat類的作用
把時間對象轉化成指定格式的字符串。反之婿斥,把指定格式的字符串轉化成時間對象。DateFormat是一個抽象類哨鸭,一般使用它的的子類SimpleDateFormat類來實現(xiàn)民宿。
public void test() throws ParseException {
SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd");
// 將時間對象轉換成字符串
String daytime = s1.format(new Date());
System.out.println(daytime); //2020-01-14 09:18:28
System.out.println(s2.format(new Date()));//2020-01-14
System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date())); //09:18:28
String time = "2007-10-7";
Date date = s2.parse(time);
System.out.println("date1: " + date); //date1: Sun Oct 07 00:00:00 CST 2007
time = "2007-10-7 20:15:30";
date = s1.parse(time);
System.out.println("date2: " + date); //date2: Sun Oct 07 20:15:30 CST 2007
}
}
獲得當前時間是今年的第幾天
public class TestDateFormat2 {
public static void main(String[] args) {
SimpleDateFormat s1 = new SimpleDateFormat("D");
String daytime = s1.format(new Date());
System.out.println(daytime);
}
}
(3)Calendar日歷類
Calendar 類是一個抽象類,為我們提供了關于日期計算的相關功能像鸡,比如:年活鹰、月哈恰、日、時志群、分着绷、秒的展示和計算。GregorianCalendar 是 Calendar 的一個具體子類锌云,提供了世界上大多數國家/地區(qū)使用的標準日歷系統(tǒng)荠医。
// 設置日期
GregorianCalendar calendar2 = new GregorianCalendar();
calendar2.set(Calendar.YEAR, 2999);
calendar2.set(Calendar.MONTH, Calendar.FEBRUARY); // 月份數:0-11
calendar2.set(Calendar.DATE, 3);
calendar2.set(Calendar.HOUR_OF_DAY, 10);
calendar2.set(Calendar.MINUTE, 20);
calendar2.set(Calendar.SECOND, 23);
// 日期計算
GregorianCalendar calendar3 = new GregorianCalendar(2999, 10, 9, 22, 10, 50);
calendar3.add(Calendar.MONTH, -7); // 月份減7
calendar3.add(Calendar.DATE, 7); // 增加7天
四、 Math類
java.lang.Math提供了一系列靜態(tài)方法用于科學計算;其方法的參數和返回值類型一般為double型桑涎。如果需要更加強大的數學運算能力彬向,計算高等數學中的相關內容,可以使用apache commons下面的Math類庫攻冷。
public void test(){
//取整相關操作
System.out.println(Math.ceil(3.2));//4.0
System.out.println(Math.floor(3.2));//3.0
System.out.println(Math.round(3.2));//3
System.out.println(Math.round(3.8));//4
//絕對值娃胆、開方、a的b次冪等操作
System.out.println(Math.abs(-45));//45
System.out.println(Math.sqrt(64));//8.0
System.out.println(Math.pow(5, 2));//25.0
System.out.println(Math.pow(2, 5));//32.0
//Math類中常用的常量
System.out.println(Math.PI);//3.141592653589793
System.out.println(Math.E);//2.718281828459045
//隨機數
System.out.println(Math.random());// [0,1) 0.15899707596998602
}
}
Random類使用
public class TestRandom {
public static void main(String[] args) {
Random rand = new Random();
//隨機生成[0,1)之間的double類型的數據
System.out.println(rand.nextDouble());
//隨機生成int類型允許范圍之內的整型數據
System.out.println(rand.nextInt());
//隨機生成[0,1)之間的float類型的數據
System.out.println(rand.nextFloat());
//隨機生成false或者true
System.out.println(rand.nextBoolean());
//隨機生成[0,10)之間的int類型的數據
System.out.print(rand.nextInt(10));
//隨機生成[20,30)之間的int類型的數據
System.out.print(20 + rand.nextInt(10));
//隨機生成[20,30)之間的int類型的數據(此種方法計算較為復雜)
System.out.print(20 + (int) (rand.nextDouble() * 10));
}
}
五等曼、 File類
java.io.File類:代表文件和目錄里烦。 在開發(fā)中,讀取文件禁谦、生成文件胁黑、刪除文件、修改文件的屬性時經常會用到本類枷畏。
文件的創(chuàng)建
import java.io.File;
public class TestFile1 {
public static void main(String[] args) throws Exception {
System.out.println(System.getProperty("user.dir")); //本項目的目錄
File f = new File("a.txt"); //相對路徑:默認放到user.dir目錄下面
f.createNewFile();//創(chuàng)建文件
File f2 = new File("d:/b.txt");//絕對路徑
f2.createNewFile();
}
}
File類訪問屬性的基本用法
public class TestFile2 {
public static void main(String[] args) throws Exception {
File f = new File("d:/b.txt");
System.out.println("File是否存在:"+f.exists());
System.out.println("File是否是目錄:"+f.isDirectory());
System.out.println("File是否是文件:"+f.isFile());
System.out.println("File最后修改時間:"+new Date(f.lastModified()));
System.out.println("File的大斜鹄濉:"+f.length());
System.out.println("File的文件名:"+f.getName());
System.out.println("File的目錄路徑:"+f.getPath());
}
}
使用mkdir創(chuàng)建目錄
public class TestFile5 {
public static void main(String[] args) {
//指定一個文件
File file = new File("d:/sxt/b.txt");
//判斷該文件是否存在
boolean flag= file.exists();
//如果存在就刪除,如果不存在就創(chuàng)建
if(flag){
//刪除
boolean flagd = file.delete();
if(flagd){
System.out.println("刪除成功");
}else{
System.out.println("刪除失敗");
}
}else{
//創(chuàng)建
boolean flagn = true;
try {
//如果目錄不存在拥诡,先創(chuàng)建目錄
File dir = file.getParentFile();
dir.mkdirs();
//創(chuàng)建文件
flagn = file.createNewFile();
System.out.println("創(chuàng)建成功");
} catch (IOException e) {
System.out.println("創(chuàng)建失敗");
e.printStackTrace();
}
}
//文件重命名(同學可以自己測試一下)
//file.renameTo(new File("d:/readme.txt"));
}
}