一、基本數據類型的包裝類
八種基本數據類型並不是對象,為了將基本類型數據和對象之間實現互相轉化,JDK 為每一個基本數據類型提供了相應的包裝類。
1.1 包裝類基本知識
Java 是面向對象的語言,但並不是「純面向對象」的,因為我們經常用到的基本數據類型就不是對象。但是我們在實際應用中經常需要將基本數據轉化成對象,以便於操作。比如:將基本數據類型存儲到 Object[ ]數組或集合中的操作等等。
為了解決這個不足,Java 在設計類時為每個基本數據類型設計了一個對應的類進行代表,這樣八個和基本數據類型對應的類統稱為包裝類(Wrapper Class)。
包裝類均位於 java.lang 包,八種包裝類和基本數據類型的對應關係如表所示:
| 基本數據類型對應的包裝類 | |
| 基本數據類型 | 包裝類 |
| byte | Byte |
| boolean | Boolean |
| short | Short |
| char | Character |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
在這八個類名中,除了 Integer 和 Character 類以外,其它六個類的類名和基本數據類型一致,只是類名的第一個字母大寫而已。
在這八個類中,除了 Character 和 Boolean 以外,其他的都是「數字型」,「數字型」都是 java.lang.Number 的子類。

Number 類是抽象類,因此它的抽象方法,所有子類都需要提供實現。Number 類提供了抽象方法:intValue()、longValue()、floatValue()、doubleValue(),意味着所有的「數字型」包裝類都可以互相轉型。
示例:
public class WrapperClassTest{
public static void main(String[] args){
Integer i=new Integer(10);
Integer j=new Integer(50);
}
}內存分析圖:

1.2 包裝類的用途
對於包裝類來說,這些類的用途主要包含兩種:
1. 作為和基本數據類型對應的類型存在,方便涉及到對象的操作,如 Object[ ]、集合等的操作。
2. 包含每種基本數據類型的相關屬性如最大值、最小值等,以及相關的操作方法(這些操作方法的作用是在基本數據類型、包裝類對象、字符串之間提供相互之間的轉化!)。
包裝類的使用:
package cn.pxy.test;
public class Test {
/**測試Integer的用法,其他包裝類與Integer類似*/
void testInteger(){
//基本類型轉化成Integer對象
Integer int1=new Integer(10);//已經廢棄,不推薦使用
Integer int2=Integer.valueOf(20);//官方推薦這種寫法
//Integer對象轉化神int
int a=int1.intValue();
//字符串轉化成Integer對象
Integer int3=Integer.parseInt("334");
Integer int4=new Integer("999");
//Integer對象轉化成字符串
String str1=int3.toString();
//一些常見int類型相關的常量
System.out.println("int能表示的最大整數:"+Integer.MAX_VALUE);
}
public static void main(String[] args) {
Test test=new Test();
test.testInteger();
}
}運行結果:

1.3 自動裝箱和拆箱
自動裝箱和拆箱就是將基本數據類型和包裝類之間進行自動的互相轉換。JDK1.5 後,Java 引入了自動裝箱(autoboxing)/拆箱(unboxing)。
自動裝箱:
基本類型的數據處於需要對象的環境中時,會自動轉為「對象」。以 Integer 為例:
在 JDK1.5 以前,這樣的代碼 Integer i = 5 是錯誤的,必須要通過 Integer i = new Integer(5) 這樣的語句來實現基本數據類型轉換成包裝類的過程;
而在 JDK1.5 以後,Java 提供了自動裝箱的功能,因此只需 Integer i = 5 這樣的語句就能實現基本數據類型轉換成包裝類, 這是因為 JVM 為我們執行 了 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()方法實現的,而自動拆箱過程是通過調用包裝類的 xxxValue()方法實現的(xxx 代表對應的基本數據類型,如 intValue()、doubleValue()等)。
自動裝箱與拆箱的功能事實上是編譯器來幫的忙,編譯器在編譯時依據您所編寫的語法,決定是否進行裝箱或拆箱動作。
所以自動裝箱與拆箱的功能是所謂的「編譯器蜜糖(Compiler Sugar)」,雖然使用這個功能很方便,但在程序運行階段您得了解 Java 的語義。
//示例
package cn.pxy.test;
public class Test2 {
/**
* 測試自動裝箱和拆箱
*/
public static void main(String[] args) {
Integer b=23;//自動裝箱
int a=new Integer(20);//自動拆箱
//下面問題需要注意
Integer c=null;
int d=c;//可以通過編譯,但此處會出現空指針異常,因為此處其實就是:c.intValue()
}
}1.4 包裝類的緩存問題
整型、char類型所對應的包裝類,在自動裝箱時,對於-128~127之間的值會進行緩存處理,其目的是提高效率。
緩存處理的原理為:如果數據在-128~127這個區間,那麼在類加載時就已經為該區間的每個數值創建了對象,並將這256個對象存放到一個名為cache的數組中。每當自動裝箱過程發生時(或者手動調用valueOf()時),就會先判斷數據是否在該區間,如果在則直接獲取數組中對應的包裝類對象的引用,如果不在該區間,則會通過new調用包裝類的構造方法來創建對象。
下面我們以Integer類為例,看一看Java為我們提供的源碼,加深對緩存技術的理解:
Integer類相關源碼:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}這段代碼中我們需要解釋下面幾個問題:
1. IntegerCache類為Integer類的一個靜態內部類,僅供Integer類使用。
2. 一般情況下 IntegerCache.low為-128,IntegerCache.high為127,
IntegerCache.cache為內部類的一個靜態屬性。
IntegerCache類相關源碼:
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static Integer[] archivedCache;
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
h = Math.max(parseInt(integerCacheHighPropValue), 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(h, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
// Load IntegerCache.archivedCache from archive, if possible
VM.initializeFromArchive(IntegerCache.class);
int size = (high - low) + 1;
// Use the archived cache if it exists and is large enough
if (archivedCache == null || size > archivedCache.length) {
Integer[] c = new Integer[size];
int j = low;
for(int i = 0; i < c.length; i++) {
c[i] = new Integer(j++);
}
archivedCache = c;
}
cache = archivedCache;
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}由上面的源碼我們可以看到,靜態代碼塊的目的就是初始化數組cache的,這個過程會在類加載時完成。
包裝類的緩存測試:
package cn.pxy.test;
public class Test2 {
public static void main(String[] args) {
Integer in1=-128;
Integer in2=-128;
System.out.println(in1==in2);//true,因為在緩存範圍內
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
}
}執行結果:

內存分析如圖:

1.5 自定義一個簡單的包裝類
package cn.pxy.test;
/**
* 定義一個簡單的包裝類
* @author 胖鹹魚
*
*/
public class MyInteger {
private int value;
private static MyInteger[] cache=new MyInteger[256];
public static final int LOW=-128;
public static final int HIGH=127;
static {
//[-128,127]
for(int i=MyInteger.LOW;i<=HIGH;i++) {
//-128,0;-127,1;-126,2;
cache[i+128]=new MyInteger(i);
}
}
public static MyInteger valueOf(int i) {
if(i>=LOW&&i<=HIGH) {
return cache[i+128];
}
return new MyInteger(i);
}
public String toString() {
return this.value+"";
}
public int intValue() {
return value;
}
private MyInteger(int i) {
this.value=i;
}
public static void main(String[] args) {
MyInteger m=MyInteger.valueOf(30);
System.out.println(m);
}
}運行結果:

二、字符串相關類
String 類、StringBuilder 類、StringBuffer 類是三個字符串相關類。String 類是的對象代表不可變的字符序列,StringBuilder 類和 StringBuffer 類代表可變字符序列。關於這三個類詳細的用法,在筆試面試以及實際開發中經常用到,我們必須掌握好它們。
2.1 String類源碼分析
String 類對象代表不可變的 Unicode 字符序列,因此我們可以將 String 對象稱為「不可變對象」。 那什麼叫做「不可變對象」呢?指的是對象內部的成員變量的值無法再改變。我們打開 String 類的源碼,如圖所示:

我們發現字符串內容全部存儲到 value[ ]數組中,而變量 value 是 final 類型的,也就是常量(即只能被賦值一次)。 這就是「不可變對象」的典型定義方式。
我們發現String 的某些方法,比如:substring()是對字符串的截取操作,但本質是讀取原字符串內容生成了新的字符串。測試代碼如下:
package cn.pxy.test;
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()));
}
}運行結果:

在遇到字符串常量之間的拼接時,編譯器會做出優化,即在編譯期間就會完成字符串的拼接。因此,在使用==進行 String 對象之間的比較時,我們需要特別注意:
//字符串拼接時的優化
package cn.pxy.test;
public class TestString2 {
public static void main(String[] args) {
//編譯器做了優化,直接在編譯的時候將字符串進行拼接
String str1="hello"+"java";//相當於str1="hello java"
String str2="hellojava";
System.out.println(str1==str2);//true
String str3="hello";
String str4="java";
//編譯的時候不知道變量中存儲的是什麼,所以沒辦法在編譯的時候優化
String str5=str3+str4;
System.out.println(str2==str5);//false
}
}運行結果:

2.2 StringBuffer和StringBuilder
StringBuffer 和 StringBuilder 非常類似,均代表可變的字符序列。 這兩個類都是抽象類 AbstractStringBuilder 的子類,方法幾乎一模一樣。打開 AbstractStringBuilder的部分源碼如下:
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char value[ ];
//以下代碼省略
}顯然,內部也是一個字符數組,但這個字符數組沒有用 final 修飾,隨時可以修改。因此,StringBuilder 和 StringBuffer 稱之為「可變字符序列」。
那兩者有什麼區別:
*StringBuffer JDK1.0 版本提供的類,線程安全,做線程同步檢查, 效率較低。
*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)
StringBuffer/StringBuilder 基本用法:
package cn.pxy.test;
public class TestStringBufferAndBuilder {
public static void main(String[] args) {
/**StringBuilder*/
StringBuilder sb=new StringBuilder();
for(int i=0;i<7;i++) {
sb.append((char)('a'+i));//追加單個字符
}
System.out.println(sb.toString());//轉換成String輸出
sb.append(",I can sing my abc!");//追加字符串
System.out.println(sb.toString());
/**StringBuffer,下面的方法同樣適用StringBuilder*/
StringBuffer sb2=new StringBuffer("胖鹹魚先生說");
sb2.insert(0, "愛").insert(0, "我");//插入字符串
System.out.println(sb2);
sb2.delete(0, 2);//刪除子字符串
System.out.println(sb2);
sb2.deleteCharAt(0).deleteCharAt(0);//刪除某個字符
System.out.println(sb2.charAt(0));//獲取某個字符
System.out.println(sb2.reverse());//字符串逆序
}
}運行結果:

2.3 不可變和可變字符序列使用陷阱
String 使用的陷阱:
String 一經初始化後,就不會再改變其內容了。對 String 字符串的操作實際上是對其副本(原始拷貝)的操作,原來的字符串一點都沒有改變。比如:String s =”a”; 創建了一個字符串s = s+”b”; 實際上原來的”a”字符串對象已經丟棄了,現在又產生了另一個字符串s+”b”(也就是”ab”)。 如果多次執行這些改變串內容的操作,會導致大量副本字符串對象存留在內存中,降低效率。如果這樣的操作放到循環中,會極大影響程序的時間和空間性能,甚至會造成服務器的崩潰。
相反,StringBuilder 和 StringBuffer 類是對原字符串本身操作的,可以對字符串進行修改而不產生副本拷貝或者產生少量的副本。因此可以在循環中使用。
示例:String和StringBuilder在字符串頻繁修改時的效率測試
package cn.pxy.test;
public class Test {
public static void main(String[] args) {
/**使用String進行字符串的拼接*/
String str8="";
//本質上使用StringBuilder拼接,但是每次循環都會生成一個StringBuilder對象
long num1=Runtime.getRuntime().freeMemory();//獲取系統剩餘的內部空間
long time1=System.currentTimeMillis();//獲取系統的當前時間
for(int i=0;i<5000;i++) {
str8=str8+i;//相當於產生了5000個對象
}
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));
}
}運行結果:

三、時間處理相關類
時間是一維的,我們需要一把刻度尺來表達和度量時間。在計算機世界,我們把 1970 年 1 月 1 日 00:00:00 定為基準時間,每個度量單位是毫秒(1 秒的千分之一)。
我們用 long 類型的變量來表示時間,從基準時間往前幾億年,往後幾億年都能表示。如果想獲得現在時刻的「時刻數值」,可以使用:
long now = System.currentTimeMillis();//代表當前時刻的毫秒數
這個「時刻數值」是所有時間類的核心值,年月日都是根據這個「數值」計算出來的。我們工作學習涉及的時間相關類有如下這些:

3.1 Date時間類(java.util.Date)
在標準 Java 類庫中包含一個 Date 類。它的對象表示一個特定的瞬間,精確到毫秒。
1.Date() 分配一個 Date 對象,並初始化此對象為系統當前的日期和時間,可以精確到毫秒)。
2.Date(long date) 分配 Date 對象並初始化此對象,以表示自從標準基準時間(稱為「曆元(epoch)」,即 1970 年 1 月 1 日 00:00:00 GMT)以來的指定毫秒數。
3.boolean after(Date when) 測試此日期是否在指定日期之後。
4.booleanbefore(Date when) 測試此日期是否在指定日期之前。
5.boolean equals(Object obj) 比較兩個日期的相等性。
6.long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以來此 Date 對象表示的毫秒數。
7.String toString() 把此 Date 對象轉換為以下形式的 String:
dow mon dd hh:mm:ss zzz yyyy 其中:dow 是一周中的某一天 (Sun、Mon、Tue、Wed、 Thu、 Fri、 Sat)。
使用示例:
package cn.pxy.test;
import java.util.Date;
public class Test {
public static void main(String[] args) {
long nowNum=System.currentTimeMillis();//當前時刻對應的毫秒數
Date d=new Date();//沒有傳參,代表當前時刻的對象
System.out.println(d.getTime());//返回時間對應的毫秒數
Date d2=new Date(1000L*3600*24*365*150);//距離1970年150年
System.out.println(d2);
}
}運行結果:

JDK1.1 之前的Date 包含了:日期操作、字符串轉化成時間對象等操作。JDK1.1 之後,日期操作一般使用Calendar 類,而字符串的轉化使用 DateFormat 類。
3.2 DateFormat類和SimpleDateFormat類
DateFormat 類的作用:
把時間對象轉化成指定格式的字符串。反之,把指定格式的字符串轉化成時間對象。DateFormat 是一個抽象類,一般使用它的的子類 SimpleDateFormat 類來實現。
示例:DateFormat類和SimpleDateFormat類的使用
package cn.pxy.test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDateFormat {
public static void main(String[] args) throws ParseException {
//new出SimpleDateFormat對象
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);
System.out.println(s2.format(new Date()));
System.out.println(new SimpleDateFormat("hh:mm:ss").format(new Date()));
//將符合指定格式的字符串轉化成時間對象,字符串格式需要和指定格式一致
String time="2027-10-07";
Date date=s2.parse(time);//字符串轉化為時間對象
System.out.println("date1:"+date);
time="2027-10-07 20:15:30";
date=s1.parse(time);
System.out.println("date2:"+date);
}
}運行結果:

| 代碼中格式化字符的含義 | |||
| 字母 | 日期或時間元素 | 表示 | 示例 |
| G | Era標誌符 | Text | AD |
| y | 年 | Year | 1996;96 |
| M | 年中的月份 | Month | July;Jul;07 |
| w | 年中的周數 | Number | 27 |
| W | 月中的周數 | Number | 2 |
| D | 年中的天數 | Number | 189 |
| d | 月中的天數 | Number | 10 |
| F | 月中的星期 | Number | 2 |
| E | 星期中的天數 | Test | Tuesday;Tue |
| a | Am/pm標記 | Test | PM |
| H | 一天中的小時數(0-23) | Number | 0 |
| k | 一天中的小時數(1-24) | Number | 24 |
| K | am/pm中的小時數(0-11) | Number | 0 |
| h | am/pm中的小時數(1-12) | Number | 12 |
| m | 小時中的分鐘數 | Number | 30 |
| s | 分鐘中的秒數 | Number | 55 |
| S | 毫秒數 | Number | 978 |
| z | 時區 | General time zone | Pacific Standard Time; PST;GMT-08:00 |
| Z | 時區 | RFC 822 time zone | 0800 |
時間格式字符也可以為我們提供其他的便利。比如:獲得當前時間是今年的第幾天。代碼如下:
package cn.pxy.test;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestDateFormat {
public static void main(String[] args) {
SimpleDateFormat s1=new SimpleDateFormat("D");
SimpleDateFormat s2=new SimpleDateFormat("yyyy-MM-dd");
System.out.println("今天是:"+s2.format(new Date()));
String daytime=s1.format(new Date());
System.out.println("今天是一年中的第幾天:"+daytime);
}
}運行結果:

3.3 Calendar日曆類
Calendar 類是一個抽象類,為我們提供了關於日期計算的相關功能,比如:年、月、日、時、分、秒的展示和計算。
GregorianCalendar 是 Calendar 的一個具體子類,提供了世界上大多數國家/地區使用的標準日曆系統。
注:月份的表示,一月是 0,二月是 1,以此類推,12 月是 11。 因為大多數人習慣於使用單詞而不是使用數字來表示月份,這樣程序也許更易讀,父類 Calendar 使用常量來表示月份:JANUARY、FEBRUARY 等等。
示例:GregorianCalendar 類和 Calendar 類的使用
package cn.pxy.test;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class TestCalendar {
public static void main(String[] args) {
//得到相關日期元素
GregorianCalendar calendar=new GregorianCalendar(2999,10,9,22,10,50);
int year=calendar.get(Calendar.YEAR);//打印2999
int month=calendar.get(Calendar.MONTH);//打印10
int day=calendar.get(Calendar.DAY_OF_MONTH);//打印9
int day2=calendar.get(Calendar.DATE);//打印9
//日:Calendar.DAY_OF_MONTH與Calendar.DATE同義
int date=calendar.get(Calendar.DAY_OF_WEEK);//打印7
//星期幾,這裡是:1-7.周日是1,周一是2.。。。周六是7
System.out.println(year);
System.out.println(month);
System.out.println(day);
System.out.println(day2);
System.out.println(date);
//設置日期
GregorianCalendar calendar2=new GregorianCalendar();
calendar2.set(Calendar.YEAR, 2999);
calendar2.set(Calendar.MONTH, Calendar.FEBRUARY);
calendar2.set(Calendar.DATE, 3);
calendar2.set(Calendar.HOUR_OF_DAY, 10);
calendar2.set(Calendar.MINUTE, 20);
calendar2.set(Calendar.SECOND, 23);
printCalendar(calendar2);
//計算日期
GregorianCalendar calendar3=new GregorianCalendar(2999,10,9,22,10,50);
calendar3.add(Calendar.MONTH, -7);//月份減7
calendar3.add(Calendar.DATE, 7);//增加7天
printCalendar(calendar3);
//日曆對象和時間對象轉換
Date d=calendar3.getTime();
GregorianCalendar calendar4=new GregorianCalendar();
calendar4.setTime(new Date());
}
static void printCalendar(Calendar calendar) {
int year=calendar.get(Calendar.YEAR);
int month=calendar.get(Calendar.MONTH)+1;
int day=calendar.get(Calendar.DAY_OF_MONTH);
int date=calendar.get(Calendar.DAY_OF_WEEK)-1;
String week=""+((date==0)?"日": date );
int hour=calendar.get(Calendar.HOUR);
int minute=calendar.get(Calendar.MINUTE);
int second=calendar.get(Calendar.SECOND);
System.out.printf("%d年%d月%d日,星期%s%d:%d:%dn",year,month,day,week+" ",hour,minute,second);
}
}運行結果:

四、其他常用類
4.1 Math類
java.lang.Math 提供了一系列靜態方法用於科學計算;其方法的參數和返回值類型一般為 double 型。如果需要更加強大的數學運算能力,計算高等數學中的相關內容,可以使用 apache commons 下面的 Math 類庫。
Math 類的常用方法:
1.abs 絕對值
2.acos,asin,atan,cos,sin,tan 三角函數
3.sqrt 平方根
4.pow(double a, double b) a 的 b 次冪
5.max(double a, double b) 取大值
6.min(double a, double b) 取小值
7.ceil(double a) 大於 a 的最小整數
8.floor(double a) 小於 a 的最大整數
9.random() 返回 0.0 到 1.0 的隨機數
10.long round(double a) double 型的數據 a 轉換為 long 型(四捨五入)
11.toDegrees(double angrad) 弧度->角度
12.toRadians(double angdeg) 角度->弧度
使用示例:
package cn.pxy.test;
public class TestMath {
public static void main(String[] args) {
//取整相關操作
System.out.println(Math.ceil(3.2));
System.out.println(Math.floor(3.2));
System.out.println(Math.round(3.2));
System.out.println(Math.round(3.8));
//絕對值、開方、a的b次冪等操作
System.out.println(Math.abs(-45));
System.out.println(Math.sqrt(64));
System.out.println(Math.pow(5, 2));
System.out.println(Math.pow(2,5));
//Math類中常用的常量
System.out.println(Math.PI);
System.out.println(Math.E);
//隨機數
System.out.println(Math.random());//[0,1)
}
}運行結果:

4.2 Random類
Math 類中雖然為我們提供了產生隨機數的方法 Math.random(),但是通常我們需要的隨機數範圍並不是[0, 1)之間的 double 類型的數據,這就需要對其進行一些複雜的運算。如果使用 Math.random()計算過於複雜的話,我們可以使用例外一種方式得到隨機數,即Random 類,這個類是專門用來生成隨機數的,並且 Math.random()底層調用的就是Random 的 nextDouble()方法。
package cn.pxy.test;
import java.util.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.println(rand.nextInt(10));
//隨機生成【20,30)之間的int類型的數據
System.out.println(20+rand.nextInt(10));
//隨機生成【20,30)之間的int類型的數據(此方法計算比較複雜)
System.out.println(20+(int)(rand.nextDouble()*10));
}
}執行結果:

4.3 File類
File 類用來代表文件和目錄。
File 類的基本用法
java.io.File 類:代表文件和目錄。 在開發中,讀取文件、生成文件、刪除文件、修改文件的屬性時經常會用到本類。
File 類的常見構造方法:public File(String pathname)
以 pathname 為路徑創建 File 對象,如果 pathname 是相對路徑,則默認的當前路徑在系統屬性 user.dir 中存儲,如示例:
package cn.pxy.test;
import java.io.File;
import java.io.IOException;
public class TestFile1 {
public static void main(String[] args) throws IOException {
System.out.println(System.getProperty("user.dir"));//獲取項目根路徑
File f=new File("a.txt");//相對路徑,默認放到user.dir目錄下面
f.createNewFile();//創建文件
File f2=new File("d:/b.txt");//絕對路徑
f2.createNewFile();
}
}創建結果:


通過 File 對象可以訪問文件的屬性:
| File 類訪問屬性的方法列表 | |
| 方法 | 說明 |
| public boolean exists() | 判斷 File 是否存在 |
| public boolean isDirectory() | 判斷 File 是否是目錄 |
| public boolean isFile() | 判斷 File 是否是文件 |
| public long lastModified() | 返回 File 最後修改時間 |
| public long length() | 返回 File 大小 |
| public String getName() | 返迴文件名 |
| public String getPath() | 返迴文件的目錄路徑 |
示例:
package cn.pxy.test;
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class TestFile1 {
public static void main(String[] args) throws IOException {
File f = new File("d:/b.txt");
f.createNewFile();
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());
}
}運行結果:

通過 File 對象創建空文件或目錄(在該對象所指的文件或目錄不存在的情況下)
| File 類創建文件或目錄的方法列表 | |
| 方法 | 說明 |
| createNewFile() | 創建新的File |
| delete() | 刪除File對應的文件 |
| mkdir() | 創建一個目錄;中間某個目錄缺失,則創建失敗 |
| mkdirs() | 創建多個目錄;中間某個目錄缺失,則創建該缺失目錄 |
示例:
//mkdir
package cn.pxy.test;
import java.io.File;
import java.io.IOException;
public class TestFile1 {
public static void main(String[] args) throws IOException{
File f = new File("d:/c.txt");
f.createNewFile();
f.delete();
File f2=new File("d:/電影/華語/大陸");
boolean flag=f2.mkdir();//目錄結構中有一個不存在,則不會創建整個目錄樹
System.out.println(flag);//創建失敗
}
}
//mkdirs
package cn.pxy.test;
import java.io.File;
import java.io.IOException;
public class TestFile1 {
public static void main(String[] args) throws IOException{
File f = new File("d:/c.txt");
f.createNewFile(); // 會在 d 盤下面生成 c.txt 文件
f.delete(); // 將該文件或目錄從硬盤上刪除
File f2 = new File("d:/動漫/日本/宮崎駿");
boolean flag = f2.mkdirs();//目錄結構中有一個不存在也沒關係;創建整個目錄 樹
System.out.println(flag);//創建成功
}
}
遞歸遍歷目錄結構和樹狀展現
在電影目錄下增加幾個子文件夾或者文件,用於測試。
package cn.pxy.test;
import java.io.File;
import java.io.IOException;
public class TestFile1 {
public static void main(String[] args) throws IOException{
File f=new File("d:/電影");
printFile(f,0);
}
/**
* 打印文件信息
* @param file 文件名稱
* @param level 層次數(實際是:第幾次遞歸調用)
*/
static void printFile(File file, int level) {
//輸出層次數
for(int i=0;i<level;i++) {
System.out.print("-");
}
//輸出文件名
System.out.println(file.getName());
//如果file是目錄,則獲取子文件列表,並對每個子文件進行相同操作
if(file.isDirectory()) {
File[] files=file.listFiles();
for(File temp:files) {
//遞歸調用該方法
printFile(temp,level+1);
}
}
}
}運行結果:

4.4 枚舉
JDK1.5 引入了枚舉類型。枚舉類型的定義包括枚舉聲明和枚舉體。格式如下:
enum 枚舉名 {
枚舉體(常量列表)
}
例如:
enum Season {
SPRING, SUMMER, AUTUMN, WINDER
}
所有的枚舉類型隱性地繼承自 java.lang.Enum。枚舉實質上還是類!而每個被枚舉的成員實質就是一個枚舉類型的實例,他們默認都是 public static final 修飾的。可以直接通過枚舉類型名使用它們。
注:當你需要定義一組常量時,可以使用枚舉類型。但盡量不要使用枚舉的高級特性,事實上高級特性都可以使用普通類來實現,沒有必要引入枚舉,增加程序的複雜性!
//枚舉的使用
package cn.pxy.test;
import java.util.Random;
public class TestEnum {
public static void main(String[] args) {
// 枚舉遍歷
for (Week k : Week.values()) {
System.out.println(k);
}
// switch 語句中使用枚舉
int a = new Random().nextInt(4); // 生成 0,1,2,3 的隨機數
switch (Season.values()[a]) {
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINDTER:
System.out.println("冬天");
break;
}
}
}
/**季節*/
enum Season {
SPRING, SUMMER, AUTUMN, WINDTER
}
/**星期*/
enum Week {
星期一, 星期二, 星期三, 星期四, 星期五, 星期六, 星期日
}運行結果:

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/209448.html
微信掃一掃
支付寶掃一掃