1. 程式人生 > 實用技巧 >高德地圖百度地圖糾偏

高德地圖百度地圖糾偏

Java常用類

目錄

一、String類

StringTest01——String型別概述以及儲存位置

  1. String表示字串型別,屬於引用資料型別,不屬於基本資料型別。

  2. 在java中隨便使用雙引號括起來的都是String物件。例如:"abc","def","hello world!",這是3個String物件。

  3. java中規定,雙引號括起來的字串,是不可變的,也就是說"abc"自出生到最終死亡,不可變,不能變成"abcd",也不能變成"ab"。

  4. 在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";
    }
}

這個示例對應的記憶體圖:

  1. 首先在java虛擬機器的方法區會存放位元組碼檔案、程式碼片段、靜態變數和字串常量池

  2. 當程式執行時,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

  1. 使用==比較兩個物件時,比較的是兩個物件的記憶體首地址。

  2. 使用equals方法比較兩個物件:

    如果不重寫equals方法的話,使用的是Object類的equals方法,使用的==比較物件的首地址。

    如果重寫了equals方法,比較的是內容。

  3. 所以在對字串物件進行比較時:

    如果比較是不是同一個物件,使用==.

    如果比較的是兩個字串物件的內容,使用equals

  4. String類已經重寫了equals方法,呼叫表示比較的內容。

  5. 使用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類當中常用方法【重點】

  1. char charAt(int index):返回字串中指定位置的字元。

  2. int compareTo(String anotherString):比較兩個字串的大小。(-1,0,1)

  3. boolean contains(CharSequence s):判斷當前字串是否包含某個字元序列(字串)。

  4. boolean endsWith(String suffix):判斷當前字串是否以某個子字串結尾。

  5. boolean equals(Object anObject): 比較兩個字串必須使用equals方法。

    equal() 和 compareTo() 方法的區別?

    equals只能看出相等不相等。

    compareTo方法可以看出是否相等,並且同時還可以看出誰大誰小。

  6. boolean equalsIgnoreCase(String anotherString):判斷兩個字串是否相等(忽略大小寫)。

  7. byte[] getBytes():將字串物件轉換成位元組陣列。

  8. int indexOf(String str):返回某個子字串在當前字串中第一次出現處的索引(下標)。

  9. boolean isEmpty():判斷某個字串是否為“空字串”。底層原始碼呼叫的是該字串的length()方法。

  10. int length():返回字串的長度。

    面試題:判斷陣列長度和判斷字串長度不一樣?

    判斷陣列長度是length屬性,判斷字串長度是length()方法。

  11. int lastIndexOf(String str):返回某個子字串在當前字串中最後一次出現的索引(下標)。

  12. String replace(CharSequence target, CharSequence replacement):簡單來說,就是用一個字串來替換當前字串中的某個(子)字串,返回一個新的字串。

  13. String[] split(String regex):將當前字串按照某個字元(字串)進行拆分,返回一個拆分後的陣列。

  14. boolean startsWith(String prefix):判斷當前字串是否以指定字串開頭。

  15. String substring(int beginIndex) :返回當前字串的字串,從起始下標處到字串末尾。

  16. String substring(int beginIndex, int endIndex):返回當前字串的字串,從起始下標處到結束下標【前閉後開】。

    前閉後開的意思就是:包括起始下標,不包括結束下標。

  17. char[] toCharArray():將當前字串轉換成char陣列。

  18. String toLowerCase():轉換為小寫。

  19. String toUpperCase():轉化為大寫。

  20. String trim():去除字串前後空格。

    String s = " Hello World ";

    去除前後空格:String s="Hello World";

    只是字串前後的空格,字串中間的空格不會被去除。

  21. 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類的構造方法:

  1. Integer(int):將int基本型別轉化為包裝型別。
  2. 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——獲得對應包裝型別的最大值、最小值

ByteShortIntegerLongDoubleFloat都可以通過這種方式獲得最大值和最小值。

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類當中有一些常用的方法

  1. Integer x = new Integer(1000):將int型的資料轉化為包裝型別,(手動裝箱).

  2. int y = x.intValue():將Integer型別轉化為int型(手動拆箱).

  3. double doubleValue(): 以 double 型別返回該 Integer 的值。

  4. float floatValue():以 float 型別返回該 Integer 的值。

  5. long longValue(): 以 long 型別返回該 Integer 的值。

  6. short shortValue(): 以 short型別返回該 Integer 的值。

  7. static int parseInt(String s):將String型別轉化為Int型別。

    靜態方法:Integer.parseInt(String s)

    注意s需要是數字字串,如“123”,否則會報異常:NumberFormatException

  8. static String toBinaryString(int i):將十進位制 i 轉化為2進位制字串。

  9. static String toHexString(int i):將十進位制 i 轉化為16進位制字串。

  10. static String toOctalString(int i):將十進位制 i 轉化為8進位制字串。

  11. static Integer valueOf(int i):返回一個表示指定的 int 值的 Integer 例項。

  12. 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

        // 獲取“去年的今天”的時間
        // 自己玩。
    }
}