高德地圖百度地圖糾偏
Java常用類
目錄
一、String類
StringTest01——String型別概述以及儲存位置
-
String表示字串型別,屬於引用資料型別,不屬於基本資料型別。
-
在java中隨便使用雙引號括起來的都是String物件。例如:"abc","def","hello world!",這是3個String物件。
-
java中規定,雙引號括起來的字串,是不可變的,也就是說"abc"自出生到最終死亡,不可變,不能變成"abcd",也不能變成"ab"。
-
在JDK當中雙引號括起來的字串,例如:"abc" "def"都是直接儲存在“方法區”的“字串常量池”當中的。
為什麼SUN公司把字串儲存在一個“字串常量池”當中呢。因為字串在實際的開發中使用太頻繁。為了執行效率,
所以把字串放到了方法區的字串常量池當中。
package com.example.javase.string;
public class StringTest01 {
public static void main(String[] args) {
// 這兩行程式碼表示底層建立了3個字串物件,都在字串常量池當中。
String s1 = "abcdef";
String s2 = "abcdef" + "xy";
// 分析:這是使用new的方式建立的字串物件。這個程式碼中的"xy"是從哪裡來的?
// 凡是雙引號括起來的都在字串常量池中有一份。
// new物件的時候一定在堆記憶體當中開闢空間。
String s3 = new String("xy");
// i變數中儲存的是100這個值。
int i = 100;
// s變數中儲存的是字串物件的記憶體地址。
// s引用中儲存的不是"abc",是0x1111
// 而0x1111是"abc"字串物件在“字串常量池”當中的記憶體地址。
String s = "abc";
}
}
這個示例對應的記憶體圖:
-
首先在java虛擬機器的方法區會存放位元組碼檔案、程式碼片段、靜態變數和字串常量池。
-
當程式執行時,main方法棧幀會被壓入棧中,然後執行:
-
String s1 = "abcdef"
,會在方法區建立 "abcdef" 常量,然後s1存放這個常量的記憶體地址。 -
String s2 = "abcdef" + "xy"
,"abcdef" 常量在方法區已經存在了,還需要建立一個 "xy" 常量,然後通過字串拼接成"abcdefxy" 放入方法區。 -
String s3 = new String("xy")
,在堆記憶體開闢出一塊空間,存放String物件,s3存放的是String物件的記憶體地址,String物件存放的是字串常量池中的 "xy"的記憶體地址。由於"xy"在字串常量池中已經存在一份了,所以不會被再次建立。
-
String型別的引用中同樣也是儲存了物件的記憶體地址:
Spring的面試題:
StringTest02——”==“與equals
-
使用
==
比較兩個物件時,比較的是兩個物件的記憶體首地址。 -
使用
equals
方法比較兩個物件:如果不重寫
equals
方法的話,使用的是Object
類的equals
方法,使用的==
比較物件的首地址。如果重寫了
equals
方法,比較的是內容。 -
所以在對字串物件進行比較時:
如果比較是不是同一個物件,使用
==
.如果比較的是兩個字串物件的內容,使用
equals
。 -
String
類已經重寫了equals
方法,呼叫表示比較的內容。 -
使用equals比較時,需要注意的是:
建議使用:
"testString".equals(s2)
這種形式。不推薦使用:
(s2).equals"testString"
,因為可能會出現空指標異常。
package com.bjpowernode.javase.string;
public class StringTest02 {
public static void main(String[] args) {
String s1 = "hello";
// "hello"是儲存在方法區的字串常量池當中
// 所以這個"hello"不會新建。(因為這個物件已經存在了!)
String s2 = "hello";
// 分析結果是true還是false?
// == 雙等號比較的是不是變數中儲存的記憶體地址?是的。
System.out.println(s1 == s2); // true
String x = new String("xyz");
String y = new String("xyz");
// 分析結果是true還是false?
// == 雙等號比較的是不是變數中儲存的記憶體地址?是的。
System.out.println(x == y); //false
// 通過這個案例的學習,我們知道了,字串物件之間的比較不能使用“==”
// "=="不保險。應該呼叫String類的equals方法。
// String類已經重寫了equals方法,以下的equals方法呼叫的是String重寫之後的equals方法。
System.out.println(x.equals(y)); // true
String k = new String("testString");
//String k = null;
// "testString"這個字串可以後面加"."呢?
// 因為"testString"是一個String字串物件。只要是物件都能呼叫方法。
System.out.println("testString".equals(k)); // 建議使用這種方式,因為這個可以避免空指標異常。
System.out.println(k.equals("testString")); // 存在空指標異常的風險。不建議這樣寫。
}
}
StringTest03——分析以下程式,一共建立了幾個物件?
String s1 = new String("hello")
String s2 = new String("hello")
分析:一個建立了3個物件,"hello" 物件被放入了方法區的字串常量池中,new的兩個String物件放在了方法區。
package com.bjpowernode.javase.string;
/*
分析以下程式,一共建立了幾個物件
*/
public class StringTest03 {
public static void main(String[] args) {
/*
一共3個物件:
方法區字串常量池中有1個:"hello"
堆記憶體當中有兩個String物件。
一共3個。
*/
String s1 = new String("hello");
String s2 = new String("hello");
}
}
StringTest04——關於String類中常用的構造方法
- 第一個:
String s = new String("");
- 第二個:
String s = "";
最常用。 - 第三個:
String s = new String(char陣列);
- 第四個:
String s = new String(char陣列,起始下標,長度);
- 第五個:
String s = new String(byte陣列);
- 第六個:
String s = new String(byte陣列,起始下標,長度)
package com.bjpowernode.javase.string;
/**
* 關於String類中的構造方法。
* 第一個:String s = new String("");
* 第二個:String s = ""; 最常用
* 第三個:String s = new String(char陣列);
* 第四個:String s = new String(char陣列,起始下標,長度);
* 第五個:String s = new String(byte陣列);
* 第六個:String s = new String(byte陣列,起始下標,長度)
*/
public class StringTest04 {
public static void main(String[] args) {
// 建立字串物件最常用的一種方式
String s1 = "hello world!";
// s1這個變數中儲存的是一個記憶體地址。
// 按說以下應該輸出一個地址。
// 但是輸出一個字串,說明String類已經重寫了toString()方法。
System.out.println(s1);//hello world!
System.out.println(s1.toString()); //hello world!
// 這裡只掌握常用的構造方法。
byte[] bytes = {97, 98, 99}; // 97是a,98是b,99是c
String s2 = new String(bytes);
// 前面說過:輸出一個引用的時候,會自動呼叫toString()方法,預設Object的話,會自動輸出物件的記憶體地址。
// 通過輸出結果我們得出一個結論:String類已經重寫了toString()方法。
// 輸出字串物件的話,輸出的不是物件的記憶體地址,而是字串本身。
System.out.println(s2.toString()); //abc
System.out.println(s2); //abc
// String(位元組陣列,陣列元素下標的起始位置,長度)
// 將byte陣列中的一部分轉換成字串。
String s3 = new String(bytes, 1, 2);
System.out.println(s3); // bc
// 將char陣列全部轉換成字串
char[] chars = {'我','是','中','國','人'};
String s4 = new String(chars);
System.out.println(s4);
// 將char陣列的一部分轉換成字串
String s5 = new String(chars, 2, 3);
System.out.println(s5);
String s6 = new String("helloworld!");
System.out.println(s6); //helloworld!
}
}
StringTest05——String類當中常用方法【重點】
-
char charAt(int index)
:返回字串中指定位置的字元。 -
int compareTo(String anotherString)
:比較兩個字串的大小。(-1,0,1) -
boolean contains(CharSequence s)
:判斷當前字串是否包含某個字元序列(字串)。 -
boolean endsWith(String suffix)
:判斷當前字串是否以某個子字串結尾。 -
boolean equals(Object anObject)
: 比較兩個字串必須使用equals方法。equal() 和 compareTo() 方法的區別?
equals只能看出相等不相等。
compareTo方法可以看出是否相等,並且同時還可以看出誰大誰小。
-
boolean equalsIgnoreCase(String anotherString)
:判斷兩個字串是否相等(忽略大小寫)。 -
byte[] getBytes()
:將字串物件轉換成位元組陣列。 -
int indexOf(String str)
:返回某個子字串在當前字串中第一次出現處的索引(下標)。 -
boolean isEmpty()
:判斷某個字串是否為“空字串”。底層原始碼呼叫的是該字串的length()
方法。 -
int length()
:返回字串的長度。面試題:判斷陣列長度和判斷字串長度不一樣?
判斷陣列長度是length屬性,判斷字串長度是length()方法。
-
int lastIndexOf(String str)
:返回某個子字串在當前字串中最後一次出現的索引(下標)。 -
String replace(CharSequence target, CharSequence replacement)
:簡單來說,就是用一個字串來替換當前字串中的某個(子)字串,返回一個新的字串。 -
String[] split(String regex)
:將當前字串按照某個字元(字串)進行拆分,返回一個拆分後的陣列。 -
boolean startsWith(String prefix)
:判斷當前字串是否以指定字串開頭。 -
String substring(int beginIndex)
:返回當前字串的字串,從起始下標處到字串末尾。 -
String substring(int beginIndex, int endIndex)
:返回當前字串的字串,從起始下標處到結束下標【前閉後開】。前閉後開的意思就是:包括起始下標,不包括結束下標。
-
char[] toCharArray()
:將當前字串轉換成char陣列。 -
String toLowerCase()
:轉換為小寫。 -
String toUpperCase()
:轉化為大寫。 -
String trim()
:去除字串前後空格。String s = " Hello World ";
去除前後空格:String s="Hello World";
只是字串前後的空格,字串中間的空格不會被去除。
-
String.valueOf()
:將指定型別的非字串轉換為字串。如:int、boolean、float...等基本資料型別。
也可以是一個物件
String.valueOf(new Person());
注意:如果Person物件沒有重寫toString方法?
返回的字串是該物件的記憶體地址:com.example.javase.string.Person@10f87f48
重寫toString()之後返回的是一個重寫之後的字串:我是VIP客戶。
擴充套件:println()方法的原始碼是如何實現的?
System.out.println()這個方法在輸出任何資料的時候都是先轉換成字串,再輸出。
public void print(int i) { write(String.valueOf(i)); } public void print(long l) { write(String.valueOf(l)); } public void print(Object obj) { write(String.valueOf(obj)); }
package com.bjpowernode.javase.string;
public class StringTest05 {
public static void main(String[] args) {
// String類當中常用方法。
//1(掌握).char charAt(int index)
char c = "中國人".charAt(1); // "中國人"是一個字串String物件。只要是物件就能“點.”
System.out.println(c); // 國
// 2(瞭解).int compareTo(String anotherString)
// 字串之間比較大小不能直接使用 > < ,需要使用compareTo方法。
int result = "abc".compareTo("abc");
System.out.println(result); //0(等於0) 前後一致 10 - 10 = 0
int result2 = "abcd".compareTo("abce");
System.out.println(result2); //-1(小於0) 前小後大 8 - 9 = -1
int result3 = "abce".compareTo("abcd");
System.out.println(result3); // 1(大於0) 前大後小 9 - 8 = 1
// 拿著字串第一個字母和後面字串的第一個字母比較。能分勝負就不再比較了。
System.out.println("xyz".compareTo("yxz")); // -1
// 3(掌握).boolean contains(CharSequence s)
// 判斷前面的字串中是否包含後面的子字串。
System.out.println("HelloWorld.java".contains(".java")); // true
System.out.println("http://www.baidu.com".contains("https://")); // false
// 4(掌握). boolean endsWith(String suffix)
// 判斷當前字串是否以某個子字串結尾。
System.out.println("test.txt".endsWith(".java")); // false
System.out.println("test.txt".endsWith(".txt")); // true
System.out.println("fdsajklfhdkjlsahfjkdsahjklfdss".endsWith("ss")); // true
// 5(掌握).boolean equals(Object anObject)
// 比較兩個字串必須使用equals方法,不能使用“==”
// equals方法有沒有呼叫compareTo方法? 老版本可以看一下。JDK13中並沒有呼叫compareTo()方法。
// equals只能看出相等不相等。
// compareTo方法可以看出是否相等,並且同時還可以看出誰大誰小。
System.out.println("abc".equals("abc")); // true
// 6(掌握).boolean equalsIgnoreCase(String anotherString)
// 判斷兩個字串是否相等,並且同時忽略大小寫。
System.out.println("ABc".equalsIgnoreCase("abC")); // true
// 7(掌握).byte[] getBytes()
// 將字串物件轉換成位元組陣列
byte[] bytes = "abcdef".getBytes();
for(int i = 0; i < bytes.length; i++){
System.out.println(bytes[i]);
}
// 8(掌握).int indexOf(String str)
// 判斷某個子字串在當前字串中第一次出現處的索引(下標)。
System.out.println("oraclejavac++.netc#phppythonjavaoraclec++".indexOf("java")); // 6
// 9(掌握).boolean isEmpty()
// 判斷某個字串是否為“空字串”。底層原始碼呼叫的應該是字串的length()方法。
//String s = "";
String s = "a";
System.out.println(s.isEmpty());
// 10(掌握). int length()
// 面試題:判斷陣列長度和判斷字串長度不一樣
// 判斷陣列長度是length屬性,判斷字串長度是length()方法。
System.out.println("abc".length()); // 3
System.out.println("".length()); // 0
// 11(掌握).int lastIndexOf(String str)
// 判斷某個子字串在當前字串中最後一次出現的索引(下標)
System.out.println("oraclejavac++javac#phpjavapython".lastIndexOf("java")); //22
// 12(掌握). String replace(CharSequence target, CharSequence replacement)
// 替換。
// String的父介面就是:CharSequence
String newString = "http://www.baidu.com".replace("http://", "https://");
System.out.println(newString); //https://www.baidu.com
// 把以下字串中的“=”替換成“:”
String newString2 = "name=zhangsan&password=123&age=20".replace("=", ":");
System.out.println(newString2); //name:zhangsan&password:123&age:20
// 13(掌握).String[] split(String regex)
// 拆分字串
String[] ymd = "1980-10-11".split("-"); //"1980-10-11"以"-"分隔符進行拆分。
for(int i = 0; i < ymd.length; i++){
System.out.println(ymd[i]);
}
String param = "name=zhangsan&password=123&age=20";
String[] params = param.split("&");
for(int i = 0; i <params.length; i++){
System.out.println(params[i]);
// 可以繼續向下拆分,可以通過“=”拆分。
}
// 14(掌握)、boolean startsWith(String prefix)
// 判斷某個字串是否以某個子字串開始。
System.out.println("http://www.baidu.com".startsWith("http")); // true
System.out.println("http://www.baidu.com".startsWith("https")); // false
// 15(掌握)、 String substring(int beginIndex) 引數是起始下標。
// 擷取字串
System.out.println("http://www.baidu.com".substring(7)); //www.baidu.com
// 16(掌握)、String substring(int beginIndex, int endIndex)
// beginIndex起始位置(包括)
// endIndex結束位置(不包括)
System.out.println("http://www.baidu.com".substring(7, 10)); //www
// 17(掌握)、char[] toCharArray()
// 將字串轉換成char陣列
char[] chars = "我是中國人".toCharArray();
for(int i = 0; i < chars.length; i++){
System.out.println(chars[i]);
}
// 18(掌握)、String toLowerCase()
// 轉換為小寫。
System.out.println("ABCDefKXyz".toLowerCase());
// 19(掌握)、String toUpperCase();
System.out.println("ABCDefKXyz".toUpperCase());
// 20(掌握). String trim();
// 去除字串前後空白
System.out.println(" hello world ".trim());
// 21(掌握). String中只有一個方法是靜態的,不需要new物件
// 這個方法叫做valueOf
// 作用:將“非字串”轉換成“字串”
//String s1 = String.valueOf(true);
//String s1 = String.valueOf(100);
//String s1 = String.valueOf(3.14);
// 這個靜態的valueOf()方法,引數是一個物件的時候,會自動呼叫該物件的toString()方法嗎?
String s1 = String.valueOf(new Customer());
//System.out.println(s1); // 沒有重寫toString()方法之前是物件記憶體地址 com.bjpowernode.javase.string.Customer@10f87f48
System.out.println(s1); //我是一個VIP客戶!!!!
// 我們是不是可以研究一下println()方法的原始碼了?
System.out.println(100);
System.out.println(3.14);
System.out.println(true);
Object obj = new Object();
// 通過原始碼可以看出:為什麼輸出一個引用的時候,會呼叫toString()方法!!!!
// 本質上System.out.println()這個方法在輸出任何資料的時候都是先轉換成字串,再輸出。
System.out.println(obj);
System.out.println(new Customer());
}
}
class Customer {
// 重寫toString()方法
@Override
public String toString() {
return "我是一個VIP客戶!!!!";
}
}
二、StringBuffer、StringBuilder類
StringBufferTest01——String字串拼接存在的問題
思考:我們在實際的開發中,如果需要進行字串的頻繁拼接,會有什麼問題?
因為java中的字串是不可變的,每一次拼接都會產生新字串,這樣會佔用大量的方法區記憶體。造成記憶體空間的浪費。
String s = "abc";
s += "hello";
就以上兩行程式碼,就導致在方法區字串常量池當中建立了3個物件:
"abc"
"hello"
"abchello"
這些物件在字串常量池中是不會被垃圾回收器釋放的,因此是非常佔用記憶體的。
public class StringBufferTest01 {
public static void main(String[] args) {
String s = "";
// 這樣做會給java的方法區字串常量池帶來很大的壓力。
for(int i = 0; i < 100; i++){
//s += i;
s = s + i;
System.out.println(s);
}
}
}
StringBufferTest02——引入StringBuffer
1、因此如果以後需要進行大量字串的拼接操作,建議使用JDK中自帶的:
java.lang.StringBuffer
java.lang.StringBuilder
2、StringBuffer的底層實現?
- StringBuffer的底層使用的是
char[] value
陣列,往StringBuffer中存放字串,實際上是放到了陣列中了。 - 預設的無參構造的初始化容量為16。
- append方法底層在進行追加的時候,如果byte陣列滿了,會自動擴容。
3、StringBuffer與String底層實現的區別?
String使用的是
private final char value[];
StringBuffer使用的是
char value[]
因此StringBuffer是可變的。
為什麼StringBuffer是可變的?
4、如何優化StringBuffer的效能?
在建立StringBuffer的時候儘可能給定一個初始化容量。
最好減少底層陣列的擴容次數。預估計一下,給一個大一些初始化容量。
關鍵點:給一個合適的初始化容量。可以提高程式的執行效率。
public class StringBufferTest02 {
public static void main(String[] args) {
// 建立一個初始化容量為16個byte[] 陣列。(字串緩衝區物件)
StringBuffer stringBuffer = new StringBuffer();
// 拼接字串,以後拼接字串統一呼叫 append()方法。
// append是追加的意思。
stringBuffer.append("a");
stringBuffer.append("b");
stringBuffer.append("d");
stringBuffer.append(3.14);
stringBuffer.append(true);
// append方法底層在進行追加的時候,如果byte陣列滿了,會自動擴容。
stringBuffer.append(100L);
System.out.println(stringBuffer.toString());
// 指定初始化容量的StringBuffer物件(字串緩衝區物件)
StringBuffer sb = new StringBuffer(100);
sb.append("hello");
sb.append("world");
sb.append("hello");
sb.append("kitty");
System.out.println(sb);
}
}
StringBufferTest04——String為什麼是不可變的&&StringBuilder/StringBuffer為什麼是可變的?
1、面試題:String為什麼是不可變的?
在原始碼中,String
類中有一個byte[]
陣列,這個byte[]
陣列採用了final
修飾,因為陣列一旦建立長度不可變。並且被final
修飾的引用一旦指向某個物件之後,不可再指向其它物件,所以String
是不可變的!
"abc"
無法變成 "abcd"
2、StringBuilder/StringBuffer為什麼是可變的呢?
在原始碼中,tringBuffer/StringBuilder
內部實際上是一個byte[]
陣列,這個byte[]
陣列沒有被final
修飾,StringBuffer/StringBuilder
的初始化容量是16,當存滿之後會進行擴容,底層呼叫了陣列拷貝的方法
System.arraycopy()
...是這樣擴容的。所以StringBuilder/StringBuffer
適合於使用字串的頻繁拼接操作。
package com.bjpowernode.javase.stringbuffer;
public class StringBufferTest04 {
public static void main(String[] args) {
// 字串不可變是什麼意思?
// 是說雙引號裡面的字串物件一旦建立不可變。
String s = "abc"; //"abc"放到了字串常量池當中。"abc"不可變。
// s變數是可以指向其它物件的。
// 字串不可變不是說以上變數s不可變。說的是"abc"這個物件不可變。
s = "xyz";//"xyz"放到了字串常量池當中。"xyz"不可變。
}
}
StringBuilderTest01——StringBuffer和StringBuilder的區別?
StringBuffer和StringBuilder的區別?
StringBuffer中的方法都有:synchronized關鍵字修飾。表示StringBuffer在多執行緒環境下執行是安全的。
StringBuilder中的方法都沒有:synchronized關鍵字修飾,表示StringBuilder在多執行緒環境下執行是不安全的。
public class StringBuilderTest01 {
public static void main(String[] args) {
// 使用StringBuilder也是可以完成字串的拼接。
StringBuilder sb = new StringBuilder();
sb.append(100);
sb.append(true);
sb.append("hello");
sb.append("kitty");
System.out.println(sb);
}
}
三、基礎型別對應的 8 個包裝類
IntegerTest01——為什麼要再提供8種包裝類呢?
1、java中為8種基本資料型別又對應準備了8種包裝型別。8種包裝類屬於引用資料型別,父類是Object。
2、思考:為什麼要再提供8種包裝類呢?
因為8種基本資料型別不夠用。比如說呼叫
public static void doSome(Object obj){}
,想要傳入一個100進去,但是基本資料型別屬於Object,無法傳入。
所以SUN又提供對應的8種包裝型別。
package com.bjpowernode.javase.integer;
/*
1、java中為8種基本資料型別又對應準備了8種包裝型別。8種包裝類屬於引用資料型別,父類是Object。
2、思考:為什麼要再提供8種包裝類呢?
因為8種基本資料型別不夠用。
所以SUN又提供對應的8種包裝型別。
*/
public class IntegerTest01 {
//入口
public static void main(String[] args) {
// 有沒有這種需求:呼叫doSome()方法的時候需要傳一個數字進去。
// 但是數字屬於基本資料型別,而doSome()方法引數的型別是Object。
// 可見doSome()方法無法接收基本資料型別的數字。那怎麼辦呢?可以傳一個數字對應的包裝類進去。
// 把100這個數字經過構造方法包裝成物件。
MyInt myInt = new MyInt(100);
// doSome()方法雖然不能直接傳100,但是可以傳一個100對應的包裝型別。
doSome(myInt);
}
public static void doSome(Object obj){
//System.out.println(obj);
System.out.println(obj.toString());
}
}
IntegerTest02——8種基本資料型別對應的包裝型別名
1、8種基本資料型別對應的包裝型別名是什麼?
基本資料型別 包裝型別
-------------------------------------
byte java.lang.Byte(父類Number)
short java.lang.Short(父類Number)
int java.lang.Integer(父類Number)
long java.lang.Long(父類Number)
float java.lang.Float(父類Number)
double java.lang.Double(父類Number)
boolean java.lang.Boolean(父類Object)
char java.lang.Character(父類Object)
2、以上八種包裝類中,重點以java.lang.Integer
為代表進行學習,其它的型別照葫蘆畫瓢就行。
3、八種包裝類中其中6個都是數字對應的包裝類,他們的父類都是Number
,可以先研究一下Number
的公共的方法:
Number
是一個抽象類,無法例項化物件。
Number
類中有這樣的方法:
byte byteValue()
:以 byte 形式返回指定的數值。abstract double doubleValue()
:以 double 形式返回指定的數值。abstract float floatValue()
:以 float 形式返回指定的數值。abstract int intValue()
:以 int 形式返回指定的數值。abstract long longValue()
:以 long 形式返回指定的數值。short shortValue()
:以 short 形式返回指定的數值。
這些方法其實所有的數字包裝類的子類都有,這些方法是負責拆箱的。
4、什麼是拆箱和裝箱?
裝箱:基本資料型別 -(轉換為)->引用資料型別
拆箱:將引用資料型別--(轉換為)-> 基本資料型別
public class IntegerTest02 {
public static void main(String[] args) {
// 123這個基本資料型別,進行構造方法的包裝達到了:基本資料型別向引用資料型別的轉換。
// 基本資料型別 -(轉換為)->引用資料型別(裝箱)
Integer i = new Integer(123);
// 將引用資料型別--(轉換為)-> 基本資料型別
float f = i.floatValue();
System.out.println(f); //123.0
// 將引用資料型別--(轉換為)-> 基本資料型別(拆箱)
int retValue = i.intValue();
System.out.println(retValue); //123
}
}
IntegerTest03——Integer類的構造方法
Integer類的構造方法:
Integer(int)
:將int
基本型別轉化為包裝型別。Integer(String)
:將String字串轉化為Integer包裝型別。
package com.bjpowernode.javase.integer;
/*
關於Integer類的構造方法,有兩個:
Integer(int)
Integer(String)
*/
public class IntegerTest03 {
public static void main(String[] args) {
// Java9之後不建議使用這個構造方法了。出現橫線表示已過時。
// 將數字100轉換成Integer包裝型別(int --> Integer)
Integer x = new Integer(100);
System.out.println(x);
// 將String型別的數字,轉換成Integer包裝型別。(String --> Integer)
Integer y = new Integer("123");
System.out.println(y);
// double -->Double
Double d = new Double(1.23);
System.out.println(d);
// String --> Double
Double e = new Double("3.14");
System.out.println(e);
}
}
IntegerTest04——獲得對應包裝型別的最大值、最小值
Byte
、Short
、Integer
、Long
、Double
、Float
都可以通過這種方式獲得最大值和最小值。
package com.bjpowernode.javase.integer;
public class IntegerTest04 {
public static void main(String[] args) {
// 通過訪問包裝類的常量,來獲取最大值和最小值
System.out.println("int的最大值:" + Integer.MAX_VALUE); //2147483647
System.out.println("int的最小值:" + Integer.MIN_VALUE); //-2147483648
System.out.println("byte的最大值:" + Byte.MAX_VALUE); //127
System.out.println("byte的最小值:" + Byte.MIN_VALUE); //-128
}
}
IntegerTest05——自動裝箱和自動拆箱
自動裝箱:基本資料型別自動轉換成包裝類。
Integer z = 1000; // 等同於:Integer z = new Integer(1000);
z儲存的是1000的地址。
自動拆箱:包裝類自動轉換成基本資料型別。
好處:方便程式設計。
public class IntegerTest05 {
public static void main(String[] args) {
// 900是基本資料型別
// x是包裝型別
// 基本資料型別 --(自動轉換)--> 包裝型別:自動裝箱
Integer x = 900;
System.out.println(x);
// x是包裝型別
// y是基本資料型別
// 包裝型別 --(自動轉換)--> 基本資料型別:自動拆箱
int y = x;
System.out.println(y);
// z是一個引用,z是一個變數,z還是儲存了一個物件的記憶體地址。
Integer z = 1000; // 等同於:Integer z = new Integer(1000);
// 分析為什麼這個沒有報錯呢?
// +兩邊要求是基本資料型別的數字,z是包裝類,不屬於基本資料型別,這裡會進行自動拆箱。將z轉換成基本資料型別
// 在java5之前你這樣寫肯定編譯器報錯。
System.out.println(z + 1);
Integer a = 1000; // Integer a = new Integer(1000); a是個引用,儲存記憶體地址指向物件。
Integer b = 1000; // Integer b = new Integer(1000); b是個引用,儲存記憶體地址指向物件。
// == 比較的是物件的記憶體地址,a和b兩個引用中儲存的物件記憶體地址不同。
// == 這個運算子不會觸發自動拆箱機制。(只有+ - * /等運算的時候才會。)
System.out.println(a == b); //false
}
}
IntegerTest06——Integer非常重要的面試題
Java中為了提高程式的執行效率,將[-128到127]
之間所有的包裝物件提前建立好,放到了一個方法區的“整數型常量池”當中了,目的是隻要用這個區間的資料不需要再new
了,直接從整數型常量池當中取出來。
原理:x
變數中儲存的物件的記憶體地址和y
變數中儲存的物件的記憶體地址是一樣的。
package com.bjpowernode.javase.integer;
/*
這個題目是Integer非常重要的面試題。
*/
public class IntegerTest06 {
public static void main(String[] args) {
Integer a = 128;
Integer b = 128;
System.out.println(a == b); //false
/*
java中為了提高程式的執行效率,將[-128到127]之間所有的包裝物件提前建立好,
放到了一個方法區的“整數型常量池”當中了,目的是隻要用這個區間的資料不需要
再new了,直接從整數型常量池當中取出來。
原理:x變數中儲存的物件的記憶體地址和y變數中儲存的物件的記憶體地址是一樣的。
*/
Integer x = 127;
Integer y = 127;
// == 永遠判斷的都是兩個物件的記憶體地址是否相同。
System.out.println(x == y); //true
}
}
IntegerTest07——Integer類當中有一些常用的方法
-
Integer x = new Integer(1000)
:將int
型的資料轉化為包裝型別,(手動裝箱). -
int y = x.intValue()
:將Integer
型別轉化為int
型(手動拆箱). -
double doubleValue()
: 以double
型別返回該Integer
的值。 -
float floatValue()
:以float
型別返回該Integer
的值。 -
long longValue()
: 以long
型別返回該Integer
的值。 -
short shortValue()
: 以short
型別返回該Integer
的值。 -
static int parseInt(String s)
:將String型別轉化為Int型別。靜態方法:Integer.parseInt(String s)
注意s需要是數字字串,如“123”,否則會報異常:NumberFormatException
-
static String toBinaryString(int i)
:將十進位制i
轉化為2進位制字串。 -
static String toHexString(int i)
:將十進位制i
轉化為16進位制字串。 -
static String toOctalString(int i)
:將十進位制i
轉化為8進位制字串。 -
static Integer valueOf(int i)
:返回一個表示指定的int
值的Integer
例項。 -
static Integer valueOf(String s)
:返回一個表示指定的int
值的Integer
例項。
package com.bjpowernode.javase.integer;
import jdk.swing.interop.SwingInterOpUtils;
/*
總結一下之前所學的經典異常?
空指標異常:NullPointerException
型別轉換異常:ClassCastException
陣列下標越界異常:ArrayIndexOutOfBoundsException
數字格式化異常:NumberFormatException
Integer類當中有哪些常用的方法呢?
*/
public class IntegerTest07 {
public static void main(String[] args) {
// 手動裝箱
Integer x = new Integer(1000);
// 手動拆箱。
int y = x.intValue();
System.out.println(y);
Integer a = new Integer("123");
// 編譯的時候沒問題,一切符合java語法,執行時會不會出問題呢?
// 不是一個“數字”可以包裝成Integer嗎?不能。執行時出現異常。
// java.lang.NumberFormatException
//Integer a = new Integer("中文");
// 重點方法
// static int parseInt(String s)
// 靜態方法,傳參String,返回int
//網頁上文字框中輸入的100實際上是"100"字串。後臺資料庫中要求儲存100數字,此時java程式需要將"100"轉換成100數字。
int retValue = Integer.parseInt("123"); // String -轉換-> int
//int retValue = Integer.parseInt("中文"); // NumberFormatException
System.out.println(retValue + 100);
// 照葫蘆畫瓢
double retValue2 = Double.parseDouble("3.14");
System.out.println(retValue2 + 1); //4.140000000000001(精度問題)
float retValue3 = Float.parseFloat("1.0");
System.out.println(retValue3 + 1); //2.0
// -----------------------------------以下內容作為了解,不需要掌握---------------------------------------
// static String toBinaryString(int i)
// 靜態的:將十進位制轉換成二進位制字串。
String binaryString = Integer.toBinaryString(3);
System.out.println(binaryString); //"11" 二進位制字串
// static String toHexString(int i)
// 靜態的:將十進位制轉換成十六進位制字串。
String hexString = Integer.toHexString(16);
System.out.println(hexString); // "10"
// 十六進位制:1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 13 14 15 16 17 18 19 1a
hexString = Integer.toHexString(17);
System.out.println(hexString); // "11"
//static String toOctalString(int i)
// 靜態的:將十進位制轉換成八進位制字串。
String octalString = Integer.toOctalString(8);
System.out.println(octalString); // "10"
System.out.println(new Object()); //java.lang.Object@6e8cf4c6
// valueOf方法作為了解
//static Integer valueOf(int i)
// 靜態的:int-->Integer
Integer i1 = Integer.valueOf(100);
System.out.println(i1);
// static Integer valueOf(String s)
// 靜態的:String-->Integer
Integer i2 = Integer.valueOf("100");
System.out.println(i2);
}
}
IntegerTest08——String-int-Integer之間互相轉換
String-int-Integer之間互相轉換圖:
package com.bjpowernode.javase.integer;
/**
* String int Integer之間互相轉換
*/
public class IntegerTest08 {
public static void main(String[] args) {
// String --> int
int i1 = Integer.parseInt("100"); // i1是100數字
System.out.println(i1 + 1); // 101
// int --> String
String s2 = i1 + ""; // "100"字串
System.out.println(s2 + 1); // "1001"
// int --> Integer
// 自動裝箱
Integer x = 1000;
// Integer --> int
// 自動拆箱
int y = x;
// String --> Integer
Integer k = Integer.valueOf("123");
// Integer --> String
String e = String.valueOf(k);
}
}
四、日期相關類
DateTest01——Date與SimpleDateFormat的用法
1、Date
所在包:java.util.Date
2、SimpleDateFormat
所在包:java.text.SimpleDateFormat
3、使用Date如何獲得當前系統的時間?
Date nowTime = new Date();
輸出的格式是:Sun Sep 13 22:07:38 CST 2020
4、String型別的日期如何轉化為Date型別?
String day = "2017-09-09 22:09:57 653"; SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); Date date1 = sdf1.parse(day); System.out.println(date1); //Sat Sep 09 22:09:57 CST 2017
5、Date型別如何轉化為String型別的日期?
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS"); String formatDate = sdf.format(date); System.out.println(formatDate); //2020-09-13 22:09:57 653
6、SimpleDateFormat格式化日期引數的書寫規則
yyyy 年(年是4位)
MM 月(月是2位)
dd 日
HH 時
mm 分
ss 秒
SSS 毫秒(毫秒3位,最高999。1000毫秒代表1秒)
public class DateTest01 {
public static void main(String[] args) throws Exception {
// 獲取系統當前時間(精確到毫秒的系統當前時間)
// 直接呼叫無引數構造方法就行。
Date nowTime = new Date();
// java.util.Date類的toString()方法已經被重寫了。
// 輸出的應該不是一個物件的記憶體地址,應該是一個日期字串。
//System.out.println(nowTime); //Thu Mar 05 10:51:06 CST 2020
// 日期可以格式化嗎?
// 將日期型別Date,按照指定的格式進行轉換:Date --轉換成具有一定格式的日期字串-->String
// SimpleDateFormat是java.text包下的。專門負責日期格式化的。
/*
yyyy 年(年是4位)
MM 月(月是2位)
dd 日
HH 時
mm 分
ss 秒
SSS 毫秒(毫秒3位,最高999。1000毫秒代表1秒)
注意:在日期格式中,除了y M d H m s S這些字元不能隨便寫之外,剩下的符號格式自己隨意組織。
*/
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
//SimpleDateFormat sdf = new SimpleDateFormat("yy/MM/dd HH:mm:ss");
String nowTimeStr = sdf.format(nowTime);
System.out.println(nowTimeStr);
// 假設現在有一個日期字串String,怎麼轉換成Date型別?
// String --> Date
String time = "2008-08-08 08:08:08 888";
//SimpleDateFormat sdf2 = new SimpleDateFormat("格式不能隨便寫,要和日期字串格式相同");
// 注意:字串的日期格式和SimpleDateFormat物件指定的日期格式要一致。不然會出現異常:java.text.ParseException
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
Date dateTime = sdf2.parse(time);
System.out.println(dateTime); //Fri Aug 08 08:08:08 CST 2008
}
}
DateTest02——System.currentTimeMillis()的用法
package com.bjpowernode.javase.date;
/*
獲取自1970年1月1日 00:00:00 000到當前系統時間的總毫秒數。
1秒 = 1000毫秒
簡單總結一下System類的相關屬性和方法:
System.out 【out是System類的靜態變數。】
System.out.println() 【println()方法不是System類的,是PrintStream類的方法。】
System.gc() 建議啟動垃圾回收器
System.currentTimeMillis() 獲取自1970年1月1日到系統當前時間的總毫秒數。
System.exit(0) 退出JVM。
*/
public class DateTest02 {
public static void main(String[] args) {
// 獲取自1970年1月1日 00:00:00 000到當前系統時間的總毫秒數。
long nowTimeMillis = System.currentTimeMillis();
System.out.println(nowTimeMillis); //1583377912981
// 統計一個方法耗時
// 在呼叫目標方法之前記錄一個毫秒數
long begin = System.currentTimeMillis();
print();
// 在執行完目標方法之後記錄一個毫秒數
long end = System.currentTimeMillis();
System.out.println("耗費時長"+(end - begin)+"毫秒");
}
// 需求:統計一個方法執行所耗費的時長
public static void print(){
for(int i = 0; i < 1000000000; i++){
System.out.println("i = " + i);
}
}
}
DateTest03——獲得幾天前(幾月前)的日期
package com.bjpowernode.javase.date;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest03 {
public static void main(String[] args) {
// 這個時間是什麼時間?
// 1970-01-01 00:00:00 001
Date time = new Date(1); // 注意:引數是一個毫秒
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime = sdf.format(time);
// 北京是東8區。差8個小時。
System.out.println(strTime); // 1970-01-01 08:00:00 001
// 獲取昨天的此時的時間。
Date time2 = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24);
String strTime2 = sdf.format(time2);
System.out.println(strTime2); //2020-03-04 11:44:14 829
// 獲取“去年的今天”的時間
// 自己玩。
}
}