在實際開發工作中,我們會使用到一些操作,這些操作在Java中都已經封裝好了相應的類包供我們使用。
包裝類
包裝類的定義
Java是面向對象的語言,但並不是“純面向對象”的,因爲我們經常用到的基本數據類型就不是對象。但是我們在實際應用中經常需要將基本數據轉化成對象,以便於操作。
爲了解決這個問題,Java在設計類時爲每個基本數據類型設計了一個對應的類進行代表,這樣八個和基本數據類型對應的類統稱爲包裝類,以下就是每種基礎數據類型所對應的包裝類。
基礎數據類型 | 包裝類 |
---|---|
byte | Byte |
boolean | Boolean |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
包裝類的用途
- 作爲和基本數據類型對應的類型存在,方便涉及到對象的操作,如Object[]、集合等的操作。
- 包含每種基本數據類型的相關屬性如最大值、最小值等,以及相關的操作方法(這些操作方法的作用是在基本數據類型、包裝類對象、字符串之間提供相互之間的轉化!)。
以下例子歸納了包裝類的常用用法,別的不常用的方法可以查看API文檔:
public class Test {
/** 測試Integer的用法,其他包裝類與Integer類似 */
public 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();
}
}
自動裝箱和拆箱
-
自動裝箱: 基本類型的數據處於需要對象的環境中時,會自動轉爲“對象”。自動裝箱過程是通過自動調用包裝類的valueOf()方法實現的。
-
自動拆箱: 每當需要一個值時,對象會自動轉成基本數據類型,沒必要再去顯式調用intValue()、doubleValue()等轉型方法。自動拆箱過程是通過調用包裝類的xxxValue()方法實現的(xxx代表對應的基本數據類型,如intValue()、doubleValue()等)。
以下例子展示了自動裝拆箱的使用:
public class TestAutoBox {
public static void main(String[] args) {
Integer a=123; //自動裝箱:Integer a=Integer.valueOf(123);
int b=a; //自動拆箱:int b=a.intValue();
Integer c=null;
if (c!=null) { //檢測c是否爲空值,防止空指針異常
int d=c; //自動拆箱:調用了intValue();
}
}
}
包裝類的緩存問題
整型、char類型所對應的包裝類,在自動裝箱時,對於-128~127之間的值會進行緩存處理,其目的是提高效率。
緩存處理的原理爲:如果數據在-128~127這個區間,那麼在類加載時就已經爲該區間的每個數值創建了對象,並將這256個對象存放到一個名爲cache的數組中。每當自動裝箱過程發生時(或者手動調用valueOf()時),就會先判斷數據是否在該區間,如果在則直接獲取數組中對應的包裝類對象的引用,如果不在該區間,則會通過new調用包裝類的構造方法來創建對象,可以參考以下例子更直觀的明白原理:
public class Test {
public static void main(String[] args) {
//緩存[-128,127]之間的數字。實際就是系統初始的時候,創建了[-128,127]之間的一個緩存數組
//當我們調用valueOf()的時候,首先檢查是否在[-128,127]之間,如果在這個範圍則直接從緩存數組中拿出已經建好的對象
//如果不在這個範圍,則創建新的Integer對象
Integer in1=Integer.valueOf(-123);
Integer in2=-123;
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類
在Java中沒有內置的字符串類型,而是再標準Java類庫中提供了一個預定義的類,這個類就是String類,String類對象代表不可變的Unicode字符序列,因此我們可以將String對象稱爲“不可變對象”。
String類的基本用法
public class TestString {
public static void main(String[] args) {
String s1=new String("abcdef");
String s2=s1.substring(1, 5);
System.out.println(s1);
System.out.println(s2);
System.out.println("#####################");
//不是同一個對象
System.out.println(Integer.toHexString(s1.hashCode()));
System.out.println(Integer.toHexString(s2.hashCode()));
System.out.println("#####################");
//字符串的拼接
String str01="abc";
String str02=new String("def");
String str03="abc"+"defg";
String str04="18"+19; //有一個字符串就不是加法,是字符串連接符,輸出1819
//編譯器做了優化,直接在編譯的時候將字符串進行拼接
String str1="hello"+" java";
String str2="hello java";
System.out.println(str1==str2); //true
String str3="hello";
String str4=" java";
//編譯的時候不知道變量中存儲的是什麼,所以沒辦法在編譯的時候優化
String str5=str3+str4;
System.out.println(str2==str5); //false
System.out.println(str2.equals(str5)); //true,做字符串比較的時候,使用equals不要使用==
}
}
String類的常用方法
以下展示了String類常用的幾種方法,更詳細的內容在需要使用時可以查看API文檔:
public class TestStringClassVoid {
public static void main(String[] args) {
String str1="core Java";
String str2="Core Java";
System.out.println(str1.charAt(3)); //提取指定索引(3,從0開始)的字符
System.out.println(str2.length()); //字符串的長度
System.out.println(str1.equals(str2)); //比較兩個字符串是否相等
System.out.println(str1.equalsIgnoreCase(str2)); //比較兩個字符串是否相等(忽略大小寫)
System.out.println(str1.indexOf("Java")); //字符串str1中出現Java的位置(從0開始)
System.out.println(str1.indexOf("apple")); //字符串str1中出現apple的位置(從0開始,沒有出現返回-1)
String str=str1.replace(" ", "&"); //替換字符串裏的字符
System.out.println(str);
System.out.println("###################");
String s= "";
String s1="How are you?";
System.out.println(s1.startsWith("How")); //是否以"How"開頭
System.out.println(s1.endsWith("you")); //是否以"you"結尾
s=s1.substring(4); //提取子字符串:從下標爲4開始到結尾爲止(從0開始)
System.out.println(s);
s=s1.substring(4, 7); //提取子字符串[4,7) 不包括7(從0開始)
System.out.println(s);
s=s1.toUpperCase(); //轉大寫
System.out.println(s);
s=s1.toLowerCase(); //轉小寫
System.out.println(s);
String s2=" How old are you? ";
s=s2.trim(); //刪收尾空格(中間的空格不會刪除)
System.out.println(s);
System.out.println(s2); //因爲String是不可變字符串,所以s2不變(僅將結果賦給s,所以s2不變)
}
}
StringBuffer和StringBuilder
StringBuffer和StringBuilder非常類似,均代表可變的字符序列。 這兩個類都是抽象類AbstractStringBuilder的子類,方法幾乎一模一樣。
可變字符序列和不可變字符序列使用的陷阱
public class TestStringAndStringBuilder {
public static void main(String[] args) {
/**使用String進行字符串的拼接*/
String str="";
//本質上使用StringBuilder拼接,但是每次循環都會生成一個StringBuilder對象
long num1=Runtime.getRuntime().freeMemory(); //獲取系統剩餘內存空間
long time1=System.currentTimeMillis(); //獲取系統當前時間
for (int i = 0; i < 5000; i++) {
str=str+i; //相當於產生了10000個對象,每次i要加上去要產生一個i的字符串
}
long num2=Runtime.getRuntime().freeMemory();
long time2=System.currentTimeMillis();
System.out.println("String佔用內存:"+(num1-num2));
System.out.println("String佔用時間:"+(time2-time1));
/**使用StringBuilder進行字符串的拼接*/
StringBuilder sb=new StringBuilder();
long num3=Runtime.getRuntime().freeMemory(); //獲取系統剩餘內存空間
long time3=System.currentTimeMillis(); //獲取系統當前時間
for (int i = 0; i < 5000; i++) {
sb.append(i);
}
long num4=Runtime.getRuntime().freeMemory();
long time4=System.currentTimeMillis();
System.out.println("StringBuilder佔用內存:"+(num3-num4));
System.out.println("StringBuilder佔用時間:"+(time4-time3));
}
}
StringBuilder、StringBuffer的使用以及常用方法
StringBuilder和StringBuffer的方法幾乎一樣,所以以下用StringBuilder爲例:
public class TestStringBuilderVoid {
public static void main(String[] args) {
String str; //private final char value[];(不可變字符序列)
//StringBuilder線程不安全,效率高(一般使用它);StringBuffer線程安全,效率低
StringBuilder str1=new StringBuilder("abcdefg"); //char[] value;(可變字符序列)
System.out.println(Integer.hashCode(str1.hashCode()));
System.out.println(str1);
System.out.println("##############");
str1.setCharAt(2, 'S');
System.out.println(Integer.hashCode(str1.hashCode()));
System.out.println(str1);
System.out.println("###########常用方法############");
StringBuilder sb=new StringBuilder();
for (int i = 0; i < 26; i++) {
char temp=(char)('a'+i);
sb.append(temp); //在可變字符序列後加一個字符
}
System.out.println(sb);
sb.reverse(); //倒序
System.out.println(sb);
sb.setCharAt(3, '王'); //改變可變字符序列指定位置的字符
System.out.println(sb);
//因爲字符串的底層爲數組,所以它的索引值從0開始
//鏈式調用(可反覆調用),核心就是:該方法調用了return this,把自己返回了.
sb.insert(0, '6').insert(1, 5); //在指定的位置插入一個字符
System.out.println(sb);
//同樣支持鏈式調用
sb.delete(0, 2).delete(3, 4); //刪除指定位置的字符
System.out.println(sb);
}
}
String、StringBuilder和StringBuffer的使用區別
- String:不可變字符序列。
- StringBuffer:可變字符序列,並且線程安全,但是效率低。
- StringBuilder:可變字符序列,線程不安全,但是效率高(一般用它)。
時間處理類
Date類(時間類)
public class TestDate {
public static void main(String[] args) {
Date d1=new Date(2000);
System.out.println(d1);
Date d2=new Date();
System.out.println(d2.getTime()); //時間戳(輸出自從1970 年 1 月 1 日 00:00:00 GMT以來的指定毫秒數)
System.out.println(d1.after(d2)); //測試此日期是否在指定日期之後
System.out.println(d1.before(d2)); //測試此日期是否在指定日期之前
System.out.println(d1.equals(d2)); //比較兩個日期的相等性
//以後遇到時間處理:使用Candlendar類
Date date=new Date(2020-1900,0,1); //2020年1月1日
System.out.println(date);
}
}
DateFormat類和SimpleDateFormat類(時間格式轉換)
把時間對象轉化成指定格式的字符串。反之,把指定格式的字符串轉化成時間對象。
DateFormat是一個抽象類,一般使用它的的子類SimpleDateFormat類來實現。
public class TestDateFormat {
public static void main(String[] args) throws ParseException {
//把時間對象按照“格式字符串指定的格式”轉成相應的字符串
DateFormat df1=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str=df1.format(new Date(1500000));
System.out.println(str);
//把字符串按照“格式字符串指定的格式”轉成相應的時間對象
DateFormat df2=new SimpleDateFormat("yyyy年MM月dd日 hh時mm分ss秒");
Date date =df2.parse("2020年1月1日 1時1分1秒");
System.out.println(date);
//測試其他的格式字符.例如:利用w和D,獲得本時間對象所處年份的第幾周,第幾天.
DateFormat df3=new SimpleDateFormat("第w周,第D天,E");
String string=df3.format(new Date());
System.out.println(string);
}
}
格式字符串指定的格式如下圖示例:
Calendar(日曆類)
Calendar 類是一個抽象類,爲我們提供了關於日期計算的相關功能,比如:年、月、日、時、分、秒的展示和計算。
public class TestCalendar {
public static void main(String[] args) {
Calendar calendar=new GregorianCalendar(3000,0,1,1,1,1);
int year=calendar.get(Calendar.YEAR);
int month=calendar.get(Calendar.MONTH); //0-11表示對應的月份.0是一月,1是二月.........11是12月.
int day=calendar.get(Calendar.DATE); //也可使用:DATE_OF_MONTH
int weekday=calendar.get(Calendar.DAY_OF_WEEK); //1-7表示對應周幾.1是星期日,2是星期一......7是星期六
System.out.println(year+"年"+month+"月"+day+"日");
System.out.println(weekday);
System.out.println("##############");
//設置日期的相關元素
Calendar c1=new GregorianCalendar();
c1.set(Calendar.YEAR, 6666);
System.out.println(c1);
System.out.println("##############");
//日期的計算
Calendar c2=new GregorianCalendar();
c2.add(Calendar.YEAR, 100);
System.out.println(c2);
System.out.println("##############");
//日期對象和時間對象的轉化
Date date=c2.getTime();
System.out.println(date);
Calendar c3=new GregorianCalendar();
c3.setTime(new Date(2000));
System.out.println(c3);
System.out.println("##############");
printCalender(new GregorianCalendar());
}
public static void printCalender(Calendar c) {
//打印:1918年10月10日 11:23:45 週四
int year=c.get(Calendar.YEAR);
int month=c.get(Calendar.MONTH)+1; //0-11
String monthString=month<10?"0"+month:month+"";
int day=c.get(Calendar.DATE);
String dayString=day<10?"0"+day:day+"";
int hour=c.get(Calendar.HOUR);
String hourString=hour<10?"0"+hour:hour+"";
int minute=c.get(Calendar.MINUTE);
String minuteString=minute<10?"0"+minute:minute+"";
int second=c.get(Calendar.SECOND);
String secondString=second<10?"0"+second:second+"";
int dayweek=c.get(Calendar.DAY_OF_WEEK)-1; //0-6
String dayweekString="";
switch (dayweek) {
case 0:
dayweekString=" 週日";
break;
case 1:
dayweekString=" 週一";
break;
case 2:
dayweekString=" 週二";
break;
case 3:
dayweekString=" 週三";
break;
case 4:
dayweekString=" 週四";
break;
case 5:
dayweekString=" 週五";
break;
case 6:
dayweekString=" 週六";
break;
}
System.out.println(year+"年"+monthString+"月"+dayString+"日 "+hourString+":"+minuteString+":"+secondString+dayweekString);
}
}
- 注意事項
- 注意月份的表示,一月是0,二月是1,以此類推,12月是11。 因爲大多數人習慣於使用單詞而不是使用數字來表示月份,這樣程序也許更易讀,父類Calendar使用常量來表示月份:JANUARY、FEBRUARY等等。
- 週日代表的是一週的第一天
Math類
Math類的常用方法
public class TestMath {
public static void main(String[] args) {
//取整相關操作
System.out.println(Math.ceil(3.2)); //進1法
System.out.println(Math.floor(3.2)); //去掉小數取整
//四捨五入
System.out.println(Math.round(3.4));
System.out.println(Math.round(4.5));
//絕對值、開方、a的b次冪等操作
System.out.println(Math.abs(-50)); //取絕對值
System.out.println(Math.sqrt(9)); //開方
System.out.println(Math.pow(2, 3)); //a的b次冪
System.out.println(Math.pow(3, 2)); //a的b次冪
//Math類中常用的常量
System.out.println(Math.PI);
System.out.println(Math.E);
//隨機數
System.out.println(Math.random()); //[0,1)
}
}
Random類的常用方法
public class TestRandom {
public static void main(String[] args) {
Random rand=new Random();
System.out.println(rand.nextDouble()); //隨機生成[0,1)之間的double類型的數據
System.out.println(rand.nextInt()); //隨機生成int允許範圍之內的int類型數據
System.out.println(rand.nextFloat()); //隨機生成[0,1)之間的float類型的數據
System.out.println(rand.nextBoolean()); //隨機生成true或false
System.out.println(rand.nextInt(10)); //隨機生成[0,10)之間的int類型數據
System.out.println(20+rand.nextInt(10)); //隨機生成[20,30)之間的int類型數據
System.out.println(20+(int)(rand.nextDouble()*10)); //隨機生成[20,30)之間的int類型數據(此方法計算較爲複雜)
}
}
File類
路徑的常用表達
public class TestPath {
public static void main(String[] args) {
String path="D:\\test\\test.txt";
System.out.println(path);
System.out.println(File.separator);
/*路徑的表達方式(常用)*/
//1./
path="D:/test/test.txt";
System.out.println(path);
//2.File.separator常量拼接
path="D:"+File.separator+"test"+File.separator+"test.txt";
System.out.println(path);
}
}
File類的常用操作
public class TestFile {
public static void main(String[] args) throws IOException {
File file=new File("d:/a.txt");
// File file=new File("d:\\a.txt");
System.out.println(file);
//文件重命名
file.renameTo(new File("d:/bb.txt"));
//加載當前用戶目錄
System.out.println(System.getProperty("user.dir"));
//創建新文件(默認是當前用戶目錄)
File f=new File("gg.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())); //返回Date類
System.out.println("File的大小:"+f.length());
System.out.println("File的文件名:"+f.getName()); //獲取對象的名稱
//獲取對象的路徑(構建時傳入的是相對路徑就返回相對路徑,傳入絕對路徑就返回絕對路徑)
System.out.println("File的目錄路徑:"+f.getPath()); //僅顯示文件名爲當前目錄路徑
System.out.println("File的絕對目錄路徑:"+f.getAbsolutePath()); //獲取對象的絕對路徑
//獲取對象的父路徑(即文件名稱前的路徑),構建的時候有就返回,沒有就返回null
System.out.println(f.getParent());
//文件狀態判定
File fileStatus=new File("D:/a.txt");
if (null== fileStatus || !fileStatus.exists()) {
System.out.println("文件不存在!");
}else {
if (fileStatus.isFile()) {
System.out.println("文件操作");
}else {
System.out.println("文件夾操作");
}
}
System.out.println("#################");
//文件的創建以及刪除
File newFile=new File("newFile.txt");
boolean flag=newFile.createNewFile(); //創建文件,如果文件已存在,則創建失敗返回false
System.out.println(flag);
flag=newFile.delete(); //刪除已經存在的文件
System.out.println(flag);
System.out.println("#################");
//con和com3是操作系統的設備名,不能正確創建
File newFileTest=new File("D:/con");
flag=newFileTest.createNewFile();
System.out.println(flag);
//mkdir或mkdirs僅用來創建目錄不能創建文件
File f2=new File("d:/電影/華語/大陸");
boolean flag1=f2.mkdir(); //目錄結構中有一個不存在,則不會創建整個目錄樹
System.out.println(flag1); //創建失敗
File f3=new File("d:/電影/華語/大陸/");
boolean flag2=f3.mkdirs(); //目錄結構中有一個不存在也沒關係,創建整個目錄樹
System.out.println(flag2); //創建成功
System.out.println("#############");
File dir=new File("D:/eclipse-workspace/");
//list方法返回下級名稱
String[] subStrings=dir.list();
for (String s : subStrings) {
System.out.println(s);
}
System.out.println("#############");
//listFiles返回下級的所有File對象
File[] subFiles=dir.listFiles();
for (File files : subFiles) {
System.out.println(files);
}
//列出所有盤符
File[] roots=dir.listRoots();
for (File r : roots) {
System.out.println(r.getAbsolutePath());
}
}
}
枚舉類
public class TestEnum {
public static void main(String[] args) {
System.out.println(Season.SPRING);
Season season=Season.AUTUMN;
switch (season) {
case SPRING:
System.out.println("春天");
break;
case SUNMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
}
}
}
//枚舉類型隱性地繼承自java.lang.Enum,枚舉實質上還是類
//每個被枚舉的成員實質就是一個枚舉類型的實例,默認都是public static final修飾的(常量)
enum Season{
SPRING,SUNMMER,AUTUMN,WINTER
}