day18-API(常見API,對象克隆)

課程目標

能夠熟練使用Math類中的常見方法

能夠熟練使用System類中的常見方法

能夠理解Object類的常見方法作用

能夠熟練使用Objects類的常見方法

能夠熟練使用BigInteger類的常見方法

能夠熟練使用BigDecimal類的常見方法

1 Math類

1.1 概述

tips:了解內容

查看API文檔,我們可以看到API文檔中關于Math類的定義如下:

Math類所在包為java.lang包,因此在使用的時候不需要進行導包。并且Math類被final修飾了,因此該類是不能被繼承的。

Math類包含執行基本數字運算的方法,我們可以使用Math類完成基本的數學運算。

要想使用Math類我們就需要先創建該類的對象,那么創建對象就需要借助于構造方法。因此我們就需要首先查看一下API文檔,看看API文檔中針對Math類有沒有提供對應的構造方法。通過API文檔來查看

一下Math類的成員,如下所示:

在API文檔中沒有體現可用的構造方法,因此我們就不能直接通過new關鍵字去創建Math類的對象。同時我們發現Math類中的方法都是靜態的,因此在使用的時候我們可以直接通過類名去調用。在Math類中

定義了很多數學運算的方法,但是我們并不可能將所有的方法學習一遍,我們主要學習的就是一些常見的方法。

1.2 常見方法

tips:重點講解內容

常見方法介紹

我們要學習的Math的常見方法如下所示:

public static int abs(int a)					// 返回參數的絕對值
public static double ceil(double a)				// 返回大于或等于參數的最小整數
public static double floor(double a)			// 返回小于或等于參數的最大整數
public static int round(float a)				// 按照四舍五入返回最接近參數的int類型的值
public static int max(int a,int b)				// 獲取兩個int值中的較大值
public static int min(int a,int b)				// 獲取兩個int值中的較小值
public static double pow (double a,double b)	// 計算a的b次冪的值
public static double random()					// 返回一個[0.0,1.0)的隨機值

案例演示

接下來我們就來演示一些這些方法的執行效果,如下所示:

public class MathDemo01 {public static void main(String[] args) {// public static int abs(int a)         返回參數的絕對值System.out.println("-2的絕對值為:" + Math.abs(-2));System.out.println("2的絕對值為:" + Math.abs(2));// public static double ceil(double a)  返回大于或等于參數的最小整數System.out.println("大于或等于23.45的最小整數位:" + Math.ceil(23.45));System.out.println("大于或等于-23.45的最小整數位:" + Math.ceil(-23.45));// public static double floor(double a) 返回小于或等于參數的最大整數System.out.println("小于或等于23.45的最大整數位:" + Math.floor(23.45));System.out.println("小于或等于-23.45的最大整數位:" + Math.floor(-23.45));// public static int round(float a)     按照四舍五入返回最接近參數的intSystem.out.println("23.45四舍五入的結果為:" + Math.round(23.45));System.out.println("23.55四舍五入的結果為:" + Math.round(23.55));// public static int max(int a,int b)   返回兩個int值中的較大值System.out.println("23和45的最大值為: " + Math.max(23, 45));// public static int min(int a,int b)   返回兩個int值中的較小值System.out.println("12和34的最小值為: " + Math.min(12 , 34));// public static double pow (double a,double b)返回a的b次冪的值System.out.println("2的3次冪計算結果為: " + Math.pow(2,3));// public static double random()返回值為double的正值,[0.0,1.0)System.out.println("獲取到的0-1之間的隨機數為: " + Math.random());}}

運行程序進行測試,控制臺輸出結果如下:

-2的絕對值為:2
2的絕對值為:2
大于或等于23.45的最小整數位:24.0
大于或等于-23.45的最小整數位:-23.0
小于或等于23.45的最大整數位:23.0
小于或等于-23.45的最大整數位:-24.0
23.45四舍五入的結果為:23
23.55四舍五入的結果為:24
23和45的最大值為: 45
12和34的最小值為: 12
2的3次冪計算結果為: 8.0
獲取到的0-1之間的隨機數為: 0.7322484131745958

1.3 算法小題(質數)

需求:

判斷一個數是否為一個質數

代碼實現:

public class MathDemo2 {public static void main(String[] args) {//判斷一個數是否為一個質數System.out.println(isPrime(997));//997 2~996 995次}public static boolean isPrime(int number) {int count = 0;for (int i = 2; i <= Math.sqrt(number); i++) {count++;if (number % i == 0) {return false;}}System.out.println(count);return true;}
}

1.4 算法小題(自冪數)

自冪數,一個n位自然數等于自身各個數位上數字的n次冪之和

舉例1:三位數 13 + 53 + 3^3 = 153

舉例2:四位數 14 + 64 + 34 + 43 = 1634

如果自冪數是:

  • 一位自冪數,也叫做:獨身數
  • 三位自冪數:水仙花數 四位自冪數:四葉玫瑰數
  • 五位自冪數:五角星數 六位自冪數:六合數
  • 七位自冪數:北斗七星數 八位自冪數:八仙數
  • 九位自冪數:九九重陽數 十位自冪數:十全十美數

要求1:統計一共有多少個水仙花數。

要求2:(課后作業)證明沒有兩位的自冪數。

要求3:(課后作業)分別統計有多少個四葉玫瑰數和五角星數。(答案:都是3個)

//水仙花數:100 ~ 999
int count = 0;
//得到每一個三位數
for (int i = 100; i <= 999; i++) {//個位 十位 百位int ge = i % 10;int shi = i / 10 % 10;int bai = i / 100 % 10;//判斷://每一位的三次方之和 跟本身 進行比較。double sum = Math.pow(ge, 3) + Math.pow(shi, 3) + Math.pow(bai, 3);if (sum == i) {count++;//System.out.println(i);System.out.println(count);}
}

1.5 課后練習

要求2:(課后作業)證明沒有兩位的自冪數。

要求3:(課后作業)分別統計有多少個四葉玫瑰數和五角星數。(答案:都是3個)

2 System類

2.1 概述

tips:了解內容

查看API文檔,我們可以看到API文檔中關于System類的定義如下:

System類所在包為java.lang包,因此在使用的時候不需要進行導包。并且System類被final修飾了,因此該類是不能被繼承的。

System包含了系統操作的一些常用的方法。比如獲取當前時間所對應的毫秒值,再比如終止當前JVM等等。

要想使用System類我們就需要先創建該類的對象,那么創建對象就需要借助于構造方法。因此我們就需要首先查看一下API文檔,看看API文檔中針對System類有沒有提供對應的構造方法。通過API文檔來

查看一下System類的成員,如下所示:

在API文檔中沒有體現可用的構造方法,因此我們就不能直接通過new關鍵字去創建System類的對象。同時我們發現System類中的方法都是靜態的,因此在使用的時候我們可以直接通過類名去調用(Nested

Class Summary內部類或者內部接口的描述)。

2.2 常見方法

tips:重點講解內容

常見方法介紹

我們要學習的System類中的常見方法如下所示:

public static long currentTimeMillis()			// 獲取當前時間所對應的毫秒值(當前時間為0時區所對應的時間即就是英國格林尼治天文臺舊址所在位置)
public static void exit(int status)				// 終止當前正在運行的Java虛擬機,0表示正常退出,非零表示異常退出
public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos, int length); // 進行數值元素copy

案例演示

接下來我們就來通過一些案例演示一下這些方法的特點。

案例1:演示currentTimeMillis方法

public class SystemDemo01 {public static void main(String[] args) {// 獲取當前時間所對應的毫秒值long millis = System.currentTimeMillis();// 輸出結果System.out.println("當前時間所對應的毫秒值為:" + millis);}}

運行程序進行測試,控制臺的輸出結果如下:

當前時間所對應的毫秒值為:1576050298343

獲取到當前時間的毫秒值的意義:我們常常來需要統計某一段代碼的執行時間。此時我們就可以在執行這段代碼之前獲取一次時間,在執行完畢以后再次獲取一次系統時間,然后計算兩個時間的差值,

這個差值就是這段代碼執行完畢以后所需要的時間。如下代碼所示:

public class SystemDemo2 {public static void main(String[] args) {//判斷1~100000之間有多少個質數long start = System.currentTimeMillis();for (int i = 1; i <= 100000; i++) {boolean flag = isPrime2(i);if (flag) {System.out.println(i);}}long end = System.currentTimeMillis();//獲取程序運行的總時間System.out.println(end - start); //方式一:1514 毫秒  方式二:71毫秒}//以前判斷是否為質數的方式public static boolean isPrime1(int number) {for (int i = 2; i < number; i++) {if (number % i == 0) {return false;}}return true;}//改進之后判斷是否為質數的方式(效率高)public static boolean isPrime2(int number) {for (int i = 2; i <= Math.sqrt(number); i++) {if (number % i == 0) {return false;}}return true;}
}

案例2:演示exit方法

public class SystemDemo01 {public static void main(String[] args) {// 輸出System.out.println("程序開始執行了.....");// 終止JVMSystem.exit(0);// 輸出System.out.println("程序終止了..........");}}

運行程序進行測試,控制臺輸出結果如下:

程序開始執行了.....

此時可以看到在控制臺只輸出了"程序開始了...",由于JVM終止了,因此輸出"程序終止了..."這段代碼沒有被執行。

案例3:演示arraycopy方法

方法參數說明:

// src: 	 源數組
// srcPos:  源數值的開始位置
// dest:    目標數組
// destPos: 目標數組開始位置
// length:   要復制的元素個數
public static native void arraycopy(Object src,  int  srcPos, Object dest, int destPos, int length); 

代碼如下所示:

public class SystemDemo01 {public static void main(String[] args) {// 定義源數組int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56 } ;// 定義目標數組int[] desArray = new int[10] ;// 進行數組元素的copy: 把srcArray數組中從0索引開始的3個元素,從desArray數組中的1索引開始復制過去System.arraycopy(srcArray , 0 , desArray , 1 , 3);// 遍歷目標數組for(int x = 0 ; x < desArray.length ; x++) {if(x != desArray.length - 1) {System.out.print(desArray[x] + ", ");}else {System.out.println(desArray[x]);}}}}

運行程序進行測試,控制臺輸出結果如下所示:

0, 23, 45, 67, 0, 0, 0, 0, 0, 0

通過控制臺輸出結果我們可以看到,數組元素的確進行復制了。

使用這個方法我們也可以完成數組元素的刪除操作,如下所示:

public class SystemDemo02 {public static void main(String[] args) {// 定義一個數組int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56 } ;// 刪除數組中第3個元素(67):要刪除67這個元素,我們只需要將67后面的其他元素依次向前進行移動即可System.arraycopy(srcArray , 3 , srcArray , 2 , 3);// 遍歷srcArray數組for(int x = 0 ; x < srcArray.length ; x++) {if(x != desArray.length - 1) {System.out.print(srcArray[x] + ", ");}else {System.out.println(srcArray[x]);}}}
}

運行程序進行測試,控制臺的輸出結果如下所示:

23, 45, 89, 14, 56, 56 

通過控制臺輸出結果我們可以看到此時多出了一個56元素,此時我們只需要將最后一個位置設置為0即可。如下所示:

public class SystemDemo02 {public static void main(String[] args) {// 定義一個數組int[] srcArray = {23 , 45 , 67 , 89 , 14 , 56 } ;// 刪除數組中第3個元素(67):要刪除67這個元素,我們只需要將67后面的其他元素依次向前進行移動即可System.arraycopy(srcArray , 3 , srcArray , 2 , 3);// 將最后一個位置的元素設置為0srcArray[srcArray.length - 1] = 0 ;// 遍歷srcArray數組for(int x = 0 ; x < srcArray.length ; x++) {if(x != srcArray.length - 1 ) {System.out.print(srcArray[x] + ", ");}else {System.out.println(srcArray[x]);}}}
}

運行程序進行測試,控制臺輸出結果如下所示:

23, 45, 89, 14, 56, 0

此時我們可以看到元素"67"已經被刪除掉了。67后面的其他元素依次向前進行移動了一位。

arraycopy方法底層細節:

1.如果數據源數組和目的地數組都是基本數據類型,那么兩者的類型必須保持一致,否則會報錯

2.在拷貝的時候需要考慮數組的長度,如果超出范圍也會報錯

3.如果數據源數組和目的地數組都是引用數據類型,那么子類類型可以賦值給父類類型

代碼示例:

public class SystemDemo3 {public static void main(String[] args) {//public static void arraycopy(數據源數組,起始索引,目的地數組,起始索引,拷貝個數) 數組拷貝//細節://1.如果數據源數組和目的地數組都是基本數據類型,那么兩者的類型必須保持一致,否則會報錯//2.在拷貝的時候需要考慮數組的長度,如果超出范圍也會報錯//3.如果數據源數組和目的地數組都是引用數據類型,那么子類類型可以賦值給父類類型Student s1 = new Student("zhangsan", 23);Student s2 = new Student("lisi", 24);Student s3 = new Student("wangwu", 25);Student[] arr1 = {s1, s2, s3};Person[] arr2 = new Person[3];//把arr1中對象的地址值賦值給arr2中System.arraycopy(arr1, 0, arr2, 0, 3);//遍歷數組arr2for (int i = 0; i < arr2.length; i++) {Student stu = (Student) arr2[i];System.out.println(stu.getName() + "," + stu.getAge());}}
}class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}/*** 獲取** @return name*/public String getName() {return name;}/*** 設置** @param name*/public void setName(String name) {this.name = name;}/*** 獲取** @return age*/public int getAge() {return age;}/*** 設置** @param age*/public void setAge(int age) {this.age = age;}public String toString() {return "Person{name = " + name + ", age = " + age + "}";}
}class Student extends Person {public Student() {}public Student(String name, int age) {super(name, age);}
}

3 Runtime

3.1 概述

Runtime表示Java中運行時對象,可以獲取到程序運行時設計到的一些信息

3.2 常見方法

常見方法介紹

我們要學習的Object類中的常見方法如下所示:

public static Runtime getRuntime()		//當前系統的運行環境對象
public void exit(int status)			//停止虛擬機
public int availableProcessors()		//獲得CPU的線程數
public long maxMemory()				    //JVM能從系統中獲取總內存大小(單位byte)
public long totalMemory()				//JVM已經從系統中獲取總內存大小(單位byte)
public long freeMemory()				//JVM剩余內存大小(單位byte)
public Process exec(String command) 	//運行cmd命令

代碼示例:

public class RunTimeDemo1 {public static void main(String[] args) throws IOException {/*public static Runtime getRuntime() 當前系統的運行環境對象public void exit(int status) 停止虛擬機public int availableProcessors() 獲得CPU的線程數public long maxMemory() JVM能從系統中獲取總內存大小(單位byte)public long totalMemory() JVM已經從系統中獲取總內存大小(單位byte)public long freeMemory() JVM剩余內存大小(單位byte)public Process exec(string command) 運行cmd命令*///1.獲取Runtime的對象//Runtime r1 =Runtime.getRuntime();//2.exit 停止虛擬機//Runtime.getRuntime().exit(0);//System.out.println("看看我執行了嗎?");//3.獲得CPU的線程數System.out.println(Runtime.getRuntime().availableProcessors());//8//4.總內存大小,單位byte字節System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024);//4064//5.已經獲取的總內存大小,單位byte字節System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024);//254//6.剩余內存大小System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024);//251//7.運行cmd命令//shutdown :關機//加上參數才能執行//-s :默認在1分鐘之后關機//-s -t 指定時間 : 指定關機時間//-a :取消關機操作//-r: 關機并重啟Runtime.getRuntime().exec("shutdown -s -t 3600");}
}

3.3 惡搞好基友

需求:

界面上方按鈕默認隱藏

界面中間有一個提示文本和三個按鈕

當你的好基友點擊中間三個按鈕的時候就在N秒之后關機,不同的按鈕N的值不一樣

任意一個按鈕被點擊之后,上方了按鈕出現。當點擊上方按鈕之后取消關機任務

public class Test {public static void main(String[] args) {new MyJframe();}
}
public class MyJframe extends JFrame implements ActionListener {JButton yesBut = new JButton("帥爆了");JButton midBut = new JButton("一般般吧");JButton noBut = new JButton("不帥,有點磕磣");JButton dadBut = new JButton("饒了我吧!");//決定了上方的按鈕是否展示boolean flag = false;public MyJframe() {initJFrame();initView();//顯示this.setVisible(true);}private void initView() {this.getContentPane().removeAll();if (flag) {//展示按鈕dadBut.setBounds(50, 20, 100, 30);dadBut.addActionListener(this);this.getContentPane().add(dadBut);}JLabel text = new JLabel("你覺得自己帥嗎?");text.setFont(new Font("微軟雅黑", 0, 30));text.setBounds(120, 150, 300, 50);yesBut.setBounds(200, 250, 100, 30);midBut.setBounds(200, 325, 100, 30);noBut.setBounds(160, 400, 180, 30);yesBut.addActionListener(this);midBut.addActionListener(this);noBut.addActionListener(this);this.getContentPane().add(text);this.getContentPane().add(yesBut);this.getContentPane().add(midBut);this.getContentPane().add(noBut);this.getContentPane().repaint();}private void initJFrame() {//設置寬高this.setSize(500, 600);//設置標題this.setTitle("惡搞好基友");//設置關閉模式this.setDefaultCloseOperation(3);//置頂this.setAlwaysOnTop(true);//居中this.setLocationRelativeTo(null);//取消內部默認布局this.setLayout(null);}@Overridepublic void actionPerformed(ActionEvent e) {Object obj = e.getSource();if (obj == yesBut) {//給好基友一個彈框showJDialog("xxx,你太自信了,給你一點小懲罰");try {Runtime.getRuntime().exec("shutdown -s -t 3600");} catch (IOException ioException) {ioException.printStackTrace();}flag = true;initView();} else if (obj == midBut) {System.out.println("你的好基友點擊了一般般吧");//給好基友一個彈框showJDialog("xxx,你還是太自信了,也要給你一點小懲罰");try {Runtime.getRuntime().exec("shutdown -s -t 7200");} catch (IOException ioException) {ioException.printStackTrace();}flag = true;initView();} else if (obj == noBut) {System.out.println("你的好基友點擊了不帥");//給好基友一個彈框showJDialog("xxx,你還是有一點自知之明的,也要給你一點小懲罰");try {Runtime.getRuntime().exec("shutdown -s -t 1800");} catch (IOException ioException) {ioException.printStackTrace();}flag = true;initView();} else if (obj == dadBut) {//給好基友一個彈框showJDialog("xxx,這次就饒了你~");try {Runtime.getRuntime().exec("shutdown -a");} catch (IOException ioException) {ioException.printStackTrace();}}}public void showJDialog(String content) {//創建一個彈框對象JDialog jDialog = new JDialog();//給彈框設置大小jDialog.setSize(200, 150);//讓彈框置頂jDialog.setAlwaysOnTop(true);//讓彈框居中jDialog.setLocationRelativeTo(null);//彈框不關閉永遠無法操作下面的界面jDialog.setModal(true);//創建Jlabel對象管理文字并添加到彈框當中JLabel warning = new JLabel(content);warning.setBounds(0, 0, 200, 150);jDialog.getContentPane().add(warning);//讓彈框展示出來jDialog.setVisible(true);}
}

4 Object類

4.1 概述

tips:重點講解內容

查看API文檔,我們可以看到API文檔中關于Object類的定義如下:

Object類所在包是java.lang包。Object 是類層次結構的根,每個類都可以將 Object 作為超類。所有類都直接或者間接的繼承自該類;換句話說,該類所具備的方法,其他所有類都繼承了。

查看API文檔我們可以看到,在Object類中提供了一個無參構造方法,如下所示:

但是一般情況下我們很少去主動的創建Object類的對象,調用其對應的方法。更多的是創建Object類的某個子類對象,然后通過子類對象調用Object類中的方法。

4.2 常見方法

tips:重點講解內容

常見方法介紹

我們要學習的Object類中的常見方法如下所示:

public String toString()				//返回該對象的字符串表示形式(可以看做是對象的內存地址值)
public boolean equals(Object obj)		//比較兩個對象地址值是否相等;true表示相同,false表示不相同
protected Object clone()    			//對象克隆

案例演示

接下來我們就來通過一些案例演示一下這些方法的特點。

案例1:演示toString方法

實現步驟:

  1. 創建一個學生類,提供兩個成員變量(name , age);并且提供對應的無參構造方法和有參構造方法以及get/set方法
  2. 創建一個測試類(ObjectDemo01),在測試類的main方法中去創建學生對象,然后調用該對象的toString方法獲取該對象的字符串表現形式,并將結果進行輸出

如下所示:

Student類

public class Student {private String name ;       // 姓名private String age ;        // 年齡// 無參構造方法和有參構造方法以及get和set方法略...}

ObjectDemo01測試類

public class ObjectDemo01 {public static void main(String[] args) {// 創建學生對象Student s1 = new Student("itheima" , "14") ;// 調用toString方法獲取s1對象的字符串表現形式String result1 = s1.toString();// 輸出結果System.out.println("s1對象的字符串表現形式為:" + result1);}}

運行程序進行測試,控制臺輸出結果如下所示:

s1對象的字符串表現形式為:com.itheima.api.system.demo04.Student@3f3afe78

為什么控制臺輸出的結果為:com.itheima.api.system.demo04.Student@3f3afe78; 此時我們可以查看一下Object類中toString方法的源碼,如下所示:

public String toString() {		// Object類中toString方法的源碼定義return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

其中getClass().getName()對應的結果就是:com.itheima.api.system.demo04.Student;Integer.toHexString(hashCode())對應的結果就是3f3afe78。

我們常常將"com.itheima.api.system.demo04.Student@3f3afe78"這一部分稱之為對象的內存地址值。但是一般情況下獲取對象的內存地址值沒有太大的意義。獲取對象的成員變量的字符串拼接形式才

算有意義,怎么實現呢?此時我們就需要在Student類中重寫Object的toString方法。我們可以通過idea開發工具進行實現,具體步驟如下所示:

  1. 在空白處使用快捷鍵:alt + insert。此時會彈出如下的對話框

  1. 選擇toString,此時會彈出如下的對話框

同時選擇name和age屬性,點擊OK。此時就會完成toString方法的重寫,代碼如下所示:

@Override
public String toString() {return "Student{" +"name='" + name + '\'' +", age='" + age + '\'' +'}';
}

這段代碼就是把Student類中的成員變量進行了字符串的拼接。重寫完畢以后,再次運行程序,控制臺輸出結果如下所示:

s1對象的字符串表現形式為:Student{name='itheima', age='14'}

此時我們就可以清楚的查看Student的成員變量值,因此重寫toString方法的意義就是以良好的格式,更方便的展示對象中的屬性值

我們再來查看一下如下代碼的輸出:

// 創建學生對象
Student s1 = new Student("itheima" , "14") ;// 直接輸出對象s1
System.out.println(s1);

運行程序進行測試,控制臺輸出結果如下所示:

Student{name='itheima', age='14'}

我們可以看到和剛才的輸出結果是一致的。那么此時也就證明直接輸出一個對象,那么會默認調用對象的toString方法,因此如上代碼的等同于如下代碼:

// 創建學生對象
Student s1 = new Student("itheima" , "14") ;// 調用s1的toString方法,把結果進行輸出
System.out.println(s1.toString());

因此后期為了方便進行測試,我們常常是通過輸出語句直接輸出一個對象的名稱。

小結:

  1. 在通過輸出語句輸出一個對象時,默認調用的就是toString()方法
  2. 輸出地址值一般沒有意義,我們可以通過重寫toString方法去輸出對應的成員變量信息(快捷鍵:atl + insert , 空白處 右鍵 -> Generate -> 選擇toString)
  3. toString方法的作用:以良好的格式,更方便的展示對象中的屬性值
  4. 一般情況下Jdk所提供的類都會重寫Object類中的toString方法

案例2:演示equals方法

實現步驟:

  1. 在測試類(ObjectDemo02)的main方法中,創建兩個學生對象,然后比較兩個對象是否相同

代碼如下所示:

public class ObjectDemo02 {public static void main(String[] args) {// 創建兩個學生對象Student s1 = new Student("itheima" , "14") ;Student s2 = new Student("itheima" , "14") ;// 比較兩個對象是否相等System.out.println(s1 == s2);}}

運行程序進行測試,控制臺的輸出結果如下所示:

false

因為"=="號比較的是對象的地址值,而我們通過new關鍵字創建了兩個對象,它們的地址值是不相同的。因此比較結果就是false。

我們嘗試調用Object類中的equals方法進行比較,代碼如下所示:

// 調用equals方法比較兩個對象是否相等
boolean result = s1.equals(s2);// 輸出結果
System.out.println(result);

運行程序進行測試,控制臺的輸出結果為:

false

為什么結果還是false呢?我們可以查看一下Object類中equals方法的源碼,如下所示:

public boolean equals(Object obj) {		// Object類中的equals方法的源碼return (this == obj);
}

通過源碼我們可以發現默認情況下equals方法比較的也是對象的地址值。比較內存地址值一般情況下是沒有意義的,我們希望比較的是對象的屬性,如果兩個對象的屬性相同,我們認為就是同一個對象;

那么要比較對象的屬性,我們就需要在Student類中重寫Object類中的equals方法。equals方法的重寫,我們也可以使用idea開發工具完成,具體的操作如下所示:

  1. 在空白處使用快捷鍵:alt + insert。此時會彈出如下的對話框

  1. 選擇equals() and hashCode()方法,此時會彈出如下的對話框

點擊next,會彈出如下對話框:

選擇neme和age屬性點擊next,此時就會彈出如下對話框:

取消name和age屬性(因為此時選擇的是在生成hashCode方法時所涉及到的屬性,關于hashCode方法后期再做重點介紹),點擊Finish完成生成操作。生成的equals方法和hashCode方法如下:

@Override
public boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Objects.equals(name, student.name) && Objects.equals(age, student.age);	// 比較的是對象的name屬性值和age屬性值
}@Override
public int hashCode() {return 0;
}

hashCode方法我們暫時使用不到,可以將hashCode方法刪除。重寫完畢以后運行程序進行測試,控制臺輸出結果如下所示:

true

此時equals方法比較的是對象的成員變量值,而s1和s2兩個對象的成員變量值都是相同的。因此比較完畢以后的結果就是true。

小結:

  1. 默認情況下equals方法比較的是對象的地址值
  2. 比較對象的地址值是沒有意義的,因此一般情況下我們都會重寫Object類中的equals方法

案例2:對象克隆

把A對象的屬性值完全拷貝給B對象,也叫對象拷貝,對象復制

對象克隆的分類:

深克隆和淺克隆

淺克隆:

不管對象內部的屬性是基本數據類型還是引用數據類型,都完全拷貝過來

基本數據類型拷貝過來的是具體的數據,引用數據類型拷貝過來的是地址值。

Object類默認的是淺克隆

深克隆:

基本數據類型變量記錄的數據值直接拷貝過來;

字符串復用(StringTable(串池));

引用數據類型會重新創建新的

代碼實現:

package com.itheima.a04objectdemo;public class ObjectDemo4 {public static void main(String[] args) throws CloneNotSupportedException {// protected object clone(int a) 對象克隆 //1.先創建一個對象int[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0};User u1 = new User(1, "zhangsan", "1234qwer", "girl11", data);//2.克隆對象//細節://方法在底層會幫我們創建一個對象,并把原對象中的數據拷貝過去。//書寫細節://1.重寫Object中的clone方法//2.讓javabean類實現Cloneable接口//3.創建原對象并調用clone就可以了//User u2 =(User)u1.clone();//驗證一件事情:Object中的克隆是淺克隆//想要進行深克隆,就需要重寫clone方法并修改里面的方法體//int[] arr = u1.getData();//arr[0] = 100;//System.out.println(u1);//System.out.println(u2);//以后一般會用第三方工具進行克隆//1.第三方寫的代碼導入到項目中//2.編寫代碼//Gson gson =new Gson();//把對象變成一個字符串//String s=gson.toJson(u1);//再把字符串變回對象就可以了//User user =gson.fromJson(s, User.class);//int[] arr=u1.getData();//arr[0] = 100;//打印對象//System.out.println(user);}
}package com.itheima.a04objectdemo;import java.util.StringJoiner;//Cloneable
//如果一個接口里面沒有抽象方法
//表示當前的接口是一個標記性接口
//現在Cloneable表示一旦實現了,那么當前類的對象就可以被克降
//如果沒有實現,當前類的對象就不能克隆
public class User implements Cloneable {private int id;private String username;private String password;private String path;private int[] data;public User() {}public User(int id, String username, String password, String path, int[] data) {this.id = id;this.username = username;this.password = password;this.path = path;this.data = data;}/*** 獲取** @return id*/public int getId() {return id;}/*** 設置** @param id*/public void setId(int id) {this.id = id;}/*** 獲取** @return username*/public String getUsername() {return username;}/*** 設置** @param username*/public void setUsername(String username) {this.username = username;}/*** 獲取** @return password*/public String getPassword() {return password;}/*** 設置** @param password*/public void setPassword(String password) {this.password = password;}/*** 獲取** @return path*/public String getPath() {return path;}/*** 設置** @param path*/public void setPath(String path) {this.path = path;}/*** 獲取** @return data*/public int[] getData() {return data;}/*** 設置** @param data*/public void setData(int[] data) {this.data = data;}public String toString() {return "角色編號為:" + id + ",用戶名為:" + username + "密碼為:" + password + ", 游戲圖片為:" + path + ", 進度:" + arrToString();}public String arrToString() {StringJoiner sj = new StringJoiner(", ", "[", "]");for (int i = 0; i < data.length; i++) {sj.add(data[i] + "");}return sj.toString();}@Overrideprotected Object clone() throws CloneNotSupportedException {//調用父類中的clone方法//相當于讓Java幫我們克隆一個對象,并把克隆之后的對象返回出去。//先把被克隆對象中的數組獲取出來int[] data = this.data;//創建新的數組int[] newData =new int[data.length];//拷貝數組中的數據for (int i = 0; i < data.length; i++) {newData[i] = data[i];}//調用父類中的方法克隆對象User u=(User)super.clone();//因為父類中的克隆方法是淺克隆,替換克隆出來對象中的數組地址值u.data =newData;return u;}
}

5 Objects類

ps: 該equals先去判斷對象是否為空,不為空在用在對象去調用equals方法(不重寫比較的還是地址值,重寫了才是比較屬性值)

5.1 概述

tips:了解內容

查看API文檔,我們可以看到API文檔中關于Objects類的定義如下:

Objects類所在包是在java.util包下,因此在使用的時候需要進行導包。并且Objects類是被final修飾的,因此該類不能被繼承。

Objects類提供了一些對象常見操作的方法。比如判斷對象是否相等,判斷對象是否為null等等。

接下來我們來查看一下API文檔,看一下Objects類中的成員,如下所示:

我們可以發現Objects類中無無參構造方法,因此我們不能使用new關鍵字去創建Objects的對象。同時我們可以發現Objects類中所提供的方法都是靜態的。因此我們可以通過類名直接去調用這些方法。

5.2 常見方法

tips:重點講解內容

常見方法介紹

我們要重點學習的Objects類中的常見方法如下所示:

public static String toString(Object o) 					// 獲取對象的字符串表現形式
public static boolean equals(Object a, Object b)			// 比較兩個對象是否相等
public static boolean isNull(Object obj)					// 判斷對象是否為null
public static boolean nonNull(Object obj)					// 判斷對象是否不為null

我們要了解的Objects類中的常見方法如下所示:

public static <T> T requireNonNull(T obj)					// 檢查對象是否不為null,如果為null直接拋出異常;如果不是null返回該對象;
public static <T> T requireNonNullElse(T obj, T defaultObj) // 檢查對象是否不為null,如果不為null,返回該對象;如果為null返回defaultObj值
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)	// 檢查對象是否不為null,如果不為null,返回該對象;如果															 // 為null,返回由Supplier所提供的值

上述方法中的T可以理解為是Object類型。

案例演示

接下來我們就來通過一些案例演示一下Objects類中的這些方法特點。

案例1:演示重點學習方法

實現步驟:

  1. 創建一個學生類,提供兩個成員變量(name , age);并且提供對應的無參構造方法和有參構造方法以及get/set方法,并且重寫toString方法和equals方法
  2. 創建一個測試類(ObjectsDemo01), 在該類中編寫測試代碼

如下所示:

Student類

public class Student {private String name ;       // 姓名private String age ;        // 年齡// 其他代碼略...}

ObjectsDemo01測試類

public class ObjectsDemo01 {public static void main(String[] args) {// 調用方法method_04() ;}// 測試nonNull方法public static void method_04() {// 創建一個學生對象Student s1 = new Student("itheima" , "14") ;// 調用Objects類中的nonNull方法boolean result = Objects.nonNull(s1);// 輸出結果System.out.println(result);}// 測試isNull方法public static void method_03() {// 創建一個學生對象Student s1 = new Student("itheima" , "14") ;// 調用Objects類中的isNull方法boolean result = Objects.isNull(s1);// 輸出結果System.out.println(result);}// 測試equals方法public static void method_02() {// 創建兩個學生對象Student s1 = new Student("itheima" , "14") ;Student s2 = new Student("itheima" , "14") ;// 調用Objects類中的equals方法,比較兩個對象是否相等boolean result = Objects.equals(s1, s2);     // 如果Student沒有重寫Object類中的equals方法,此處比較的還是對象的地址值// 輸出結果System.out.println(result);}// 測試toString方法public static void method_01() {// 創建一個學生對象Student s1 = new Student("itheima" , "14") ;// 調用Objects中的toString方法,獲取s1對象的字符串表現形式String result = Objects.toString(s1);       // 如果Student沒有重寫Object類中的toString方法,此處還是返回的對象的地址值// 輸出結果System.out.println(result);}}

案例2:演示需要了解的方法

public class ObjectsDemo02 {public static void main(String[] args) {// 調用方法method_03();}// 演示requireNonNullElseGetpublic static void method_03() {// 創建一個學生對象Student s1 = new Student("itheima" , "14") ;// 調用Objects對象的requireNonNullElseGet方法,該方法的第二個參數是Supplier類型的,查看源碼我們發現Supplier是一個函數式接口,// 那么我們就可以為其傳遞一個Lambda表達式,而在Supplier接口中所定義的方法是無參有返回值的方法,因此具體調用所傳入的Lambda表達式如下所示Student student = Objects.requireNonNullElseGet(s1, () -> {return new Student("itcast", "14");});// 輸出System.out.println(student);}// 演示requireNonNullElsepublic static void method_02() {// 創建一個學生對象Student s1 = new Student("itheima" , "14") ;// 調用Objects對象的requireNonNullElse方法Student student = Objects.requireNonNullElse(s1, new Student("itcast", "14"));// 輸出System.out.println(student);}// 演示requireNonNullpublic static void method_01() {// 創建一個學生對象Student s1 = new Student("itheima" , "14") ;// 調用Objects對象的requireNonNull方法Student student = Objects.requireNonNull(s1);// 輸出System.out.println(student);}}

注:了解性的方法可以可以作為擴展視頻進行下發。

6 BigInteger類

6.1 引入

平時在存儲整數的時候,Java中默認是int類型,int類型有取值范圍:-2147483648 ~ 2147483647。如果數字過大,我們可以使用long類型,但是如果long類型也表示不下怎么辦呢?

就需要用到BigInteger,可以理解為:大的整數。

有多大呢?理論上最大到42億的21億次方

基本上在內存撐爆之前,都無法達到這個上限。

6.2 概述

查看API文檔,我們可以看到API文檔中關于BigInteger類的定義如下:

BigInteger所在包是在java.math包下,因此在使用的時候就需要進行導包。我們可以使用BigInteger類進行大整數的計算

6.3 常見方法

構造方法

public BigInteger(int num, Random rnd) 		//獲取隨機大整數,范圍:[0 ~ 2的num次方-1]
public BigInteger(String val) 				//獲取指定的大整數
public BigInteger(String val, int radix) 	//獲取指定進制的大整數下面這個不是構造,而是一個靜態方法獲取BigInteger對象
public static BigInteger valueOf(long val) 	//靜態方法獲取BigInteger的對象,內部有優化

構造方法小結:

  • 如果BigInteger表示的數字沒有超出long的范圍,可以用靜態方法獲取。
  • 如果BigInteger表示的超出long的范圍,可以用構造方法獲取。
  • 對象一旦創建,BigInteger內部記錄的值不能發生改變。
  • 只要進行計算都會產生一個新的BigInteger對象

常見成員方法

BigDecimal類中使用最多的還是提供的進行四則運算的方法,如下:

public BigInteger add(BigInteger val)					//加法
public BigInteger subtract(BigInteger val)				//減法
public BigInteger multiply(BigInteger val)				//乘法
public BigInteger divide(BigInteger val)				//除法
public BigInteger[] divideAndRemainder(BigInteger val)	 //除法,獲取商和余數
public  boolean equals(Object x) 					    //比較是否相同
public  BigInteger pow(int exponent) 					//次冪、次方
public  BigInteger max/min(BigInteger val) 				//返回較大值/較小值
public  int intValue(BigInteger val) 					//轉為int類型整數,超出范圍數據有誤

代碼實現:

package com.itheima.a06bigintegerdemo;import java.math.BigInteger;public class BigIntegerDemo1 {public static void main(String[] args) {/*public BigInteger(int num, Random rnd) 獲取隨機大整數,范圍:[0~ 2的num次方-11public BigInteger(String val) 獲取指定的大整數public BigInteger(String val, int radix) 獲取指定進制的大整數public static BigInteger valueOf(long val) 靜態方法獲取BigInteger的對象,內部有優化細節:對象一旦創建里面的數據不能發生改變。*///1.獲取一個隨機的大整數/* Random r=new Random();for (int i = e; i < 100; i++) {BigInteger bd1 = new BigInteger(4,r);System.out.println(bd1);//[@ ~ 15]}}*///2.獲取一個指定的大整數,可以超出long的取值范圍//細節:字符串中必須是整數,否則會報錯/* BigInteger bd2 = new BigInteger("1.1");System.out.println(bd2);*//*BigInteger bd3 = new BigInteger("abc");System.out.println(bd3);*///3.獲取指定進制的大整數//細節://1.字符串中的數字必須是整數//2.字符串中的數字必須要跟進制吻合。//比如二進制中,那么只能寫日和1,寫其他的就報錯。BigInteger bd4 = new BigInteger("123", 2);System.out.println(bd4);//4.靜態方法獲取BigInteger的對象,內部有優化//細節://1.能表示范圍比較小,只能在long的取值范圍之內,如果超出long的范圍就不行了。//2.在內部對常用的數字: -16 ~ 16 進行了優化。//  提前把-16~16 先創建好BigInteger的對象,如果多次獲取不會重新創建新的。BigInteger bd5 = BigInteger.valueOf(16);BigInteger bd6 = BigInteger.valueOf(16);System.out.println(bd5 == bd6);//trueBigInteger bd7 = BigInteger.valueOf(17);BigInteger bd8 = BigInteger.valueOf(17);System.out.println(bd7 == bd8);//false//5.對象一旦創建內部的數據不能發生改變BigInteger bd9 =BigInteger.valueOf(1);BigInteger bd10 =BigInteger.valueOf(2);//此時,不會修改參與計算的BigInteger對象中的借,而是產生了一個新的BigInteger對象記錄BigInteger result=bd9.add(bd10);System.out.println(result);//3}
}
package com.itheima.a06bigintegerdemo;import java.math.BigInteger;public class BigIntegerDemo2 {public static void main(String[] args) {/*public BigInteger add(BigInteger val) 加法public BigInteger subtract(BigInteger val) 減法public BigInteger multiply(BigInteger val) 乘法public BigInteger divide(BigInteger val) 除法,獲取商public BigInteger[] divideAndRemainder(BigInteger val) 除法,獲取商和余數public boolean equals(Object x) 比較是否相同public BigInteger pow(int exponent) 次冪public BigInteger max/min(BigInteger val) 返回較大值/較小值public int intValue(BigInteger val) 轉為int類型整數,超出范圍數據有誤*///1.創建兩個BigInteger對象BigInteger bd1 = BigInteger.valueOf(10);BigInteger bd2 = BigInteger.valueOf(5);//2.加法BigInteger bd3 = bd1.add(bd2);System.out.println(bd3);//3.除法,獲取商和余數BigInteger[] arr = bd1.divideAndRemainder(bd2);System.out.println(arr[0]);System.out.println(arr[1]);//4.比較是否相同boolean result = bd1.equals(bd2);System.out.println(result);//5.次冪BigInteger bd4 = bd1.pow(2);System.out.println(bd4);//6.maxBigInteger bd5 = bd1.max(bd2);//7.轉為int類型整數,超出范圍數據有誤/* BigInteger bd6 = BigInteger.valueOf(2147483647L);int i = bd6.intValue();System.out.println(i);*/BigInteger bd6 = BigInteger.valueOf(200);double v = bd6.doubleValue();System.out.println(v);//200.0}
}

6.4 底層存儲方式:

對于計算機而言,其實是沒有數據類型的概念的,都是0101010101,數據類型是編程語言自己規定的,所以在實際存儲的時候,先把具體的數字變成二進制,每32個bit為一組,存儲在數組中。

數組中最多能存儲元素個數:21億多

數組中每一位能表示的數字:42億多

理論上,BigInteger能表示的最大數字為:42億的21億次方。

但是還沒到這個數字,電腦的內存就會撐爆,所以一般認為BigInteger是無限的。

存儲方式如圖所示:

7 BigDecimal類

7.1 引入

首先我們來分析一下如下程序的執行結果:

public class BigDecimalDemo01 {public static void main(String[] args) {System.out.println(0.09 + 0.01);}}

這段代碼比較簡單,就是計算0.09和0.01之和,并且將其結果在控制臺進行輸出。那么按照我們的想法在控制臺輸出的結果應該為0.1。那么實際的運行結果是什么呢?我們來運行一下程序,控制臺的輸出

結果如下所示:

0.09999999999999999

這樣的結果其實就是一個丟失精度的結果。為什么會產生精度丟失呢?

在使用float或者double類型的數據在進行數學運算的時候,很有可能會產生精度丟失問題。我們都知道計算機底層在進行運算的時候,使用的都是二進制數據; 當我們在程序中寫了一個十進制數據 ,在

進行運算的時候,計算機會將這個十進制數據轉換成二進制數據,然后再進行運算,計算完畢以后計算機會把運算的結果再轉換成十進制數據給我們展示; 如果我們使用的是整數類型的數據進行計算,那

么在把十進制數據轉換成二進制數據的時候不會存在精度問題; 如果我們的數據是一個浮點類型的數據,有的時候計算機并不會將這個數據完全轉換成一個二進制數據,而是將這個將其轉換成一個無限的

趨近于這個十進數的二進制數據; 這樣使用一個不太準確的數據進行運算的時候, 最終就會造成精度丟失;為了提高精度,Java就給我們提供了BigDecimal供我們進行數據運算。

package com.itheima.a07bigdecimaldemo;import java.math.BigDecimal;public class BigDecimalDemo2 {public static void main(String[] args) {/*構造方法獲取BigDecimal對象public BigDecimal(double val) public BigDecimal(string val)靜態方法獲取BigDecimal對象public static BigDecimal valuef(double val)*///1.通過傳遞double類型的小數來創建對象//細節://這種方式有可能是不精確的,所以不建議使用BigDecimal bd1 = new BigDecimal(0.01);BigDecimal bd2 = new BigDecimal(0.09);System.out.println(bd1);System.out.println(bd2);//通過傳遞字符串表示的小數來創建對象BigDecimal bd3 = new BigDecimal("0.01");BigDecimal bd4 = new BigDecimal("0.09");BigDecimal bd5 = bd3.add(bd4);System.out.println(bd3);System.out.println(bd4);System.out.println(bd5);//3.通過靜態方法獲取對象//細節://1.如果要表示的數字不大,沒有超出double的取值范圍,建議使用靜態方法//2.如果要表示的數字比較大,超出了double的取值范圍,建議使用構造方法//3.如果我們傳遞的是0~10之間的整數,包含0,包含10,那么方法會返回已經創建好的對象,不會重新newBigDecimal bd6 = BigDecimal.valueOf(10.0);BigDecimal bd7 = BigDecimal.valueOf(10.0);System.out.println(bd6 == bd7);}
}

7.2 概述

查看API文檔,我們可以看到API文檔中關于BigDecimal類的定義如下:

BigDecimal所在包是在java.math包下,因此在使用的時候就需要進行導包。我們可以使用BigDecimal類進行更加精準的數據計算。

7.3 常見方法

構造方法

要用BigDecimal類,那么就需要首先學習一下如何去創建BigDecimal的對象。通過查看API文檔,我們可以發現Jdk中針對BigDecimal類提供了很多的構造方法,但是最常用的構造方法是:

了解完常見的構造方法以后,我們接下來就重點介紹一下常見的成員方法。

常見成員方法

BigDecimal類中使用最多的還是提供的進行四則運算的方法,如下:

public BigDecimal add(BigDecimal value)				// 加法運算
public BigDecimal subtract(BigDecimal value)		// 減法運算
public BigDecimal multiply(BigDecimal value)		// 乘法運算
public BigDecimal divide(BigDecimal value)			// 除法運算

接下來我們就來通過一些案例演示一下這些成員方法的使用。

案例1:演示基本的四則運算

代碼如下所示:

public class BigDecimalDemo01 {public static void main(String[] args) {// 創建兩個BigDecimal對象BigDecimal b1 = new BigDecimal("0.3") ;BigDecimal b2 = new BigDecimal("4") ;// 調用方法進行b1和b2的四則運算,并將其運算結果在控制臺進行輸出System.out.println(b1.add(b2));         // 進行加法運算System.out.println(b1.subtract(b2));    // 進行減法運算System.out.println(b1.multiply(b2));    // 進行乘法運算System.out.println(b1.divide(b2));      // 進行除法運算}}

運行程序進行測試,控制臺輸出結果如下:

4.3
-3.7
1.2
0.075

此時我們可以看到使用BigDecimal類來完成浮點數的計算不會存在損失精度的問題。

案例2:演示除法的特殊情況

如果使用BigDecimal類型的數據進行除法運算的時候,得到的結果是一個無限循環小數,那么就會報錯:ArithmeticException。 如下代碼所示:

public class BigDecimalDemo02 {public static void main(String[] args) {// 創建兩個BigDecimal對象BigDecimal b1 = new BigDecimal("1") ;BigDecimal b2 = new BigDecimal("3") ;// 調用方法進行b1和b2的除法運算,并且將計算結果在控制臺進行輸出System.out.println(b1.divide(b2));}}

運行程序進行測試,控制臺輸出結果如下所示:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.at java.base/java.math.BigDecimal.divide(BigDecimal.java:1716)at com.itheima.api.bigdecimal.demo02.BigDecimalDemo02.main(BigDecimalDemo02.java:14)

針對這個問題怎么解決,此時我們就需要使用到BigDecimal類中另外一個divide方法,如下所示:

BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

上述divide方法參數說明:

divisor:			除數對應的BigDecimal對象;
scale:				精確的位數;
roundingMode:		取舍模式;
取舍模式被封裝到了RoundingMode這個枚舉類中(關于枚舉我們后期再做重點講解),在這個枚舉類中定義了很多種取舍方式。最常見的取舍方式有如下幾個:
UP(直接進1) , FLOOR(直接刪除) , HALF_UP(4舍五入),我們可以通過如下格式直接訪問這些取舍模式:枚舉類名.變量名

接下來我們就來演示一下這些取舍模式,代碼如下所示:

public class BigDecimalDemo02 {public static void main(String[] args) {// 調用方法method_03() ;}// 演示取舍模式HALF_UPpublic static void method_03() {// 創建兩個BigDecimal對象BigDecimal b1 = new BigDecimal("0.3") ;BigDecimal b2 = new BigDecimal("4") ;// 調用方法進行b1和b2的除法運算,并且將計算結果在控制臺進行輸出System.out.println(b1.divide(b2 , 2 , RoundingMode.HALF_UP));}// 演示取舍模式FLOORpublic static void method_02() {// 創建兩個BigDecimal對象BigDecimal b1 = new BigDecimal("1") ;BigDecimal b2 = new BigDecimal("3") ;// 調用方法進行b1和b2的除法運算,并且將計算結果在控制臺進行輸出System.out.println(b1.divide(b2 , 2 , RoundingMode.FLOOR));}// 演示取舍模式UPpublic static void method_01() {// 創建兩個BigDecimal對象BigDecimal b1 = new BigDecimal("1") ;BigDecimal b2 = new BigDecimal("3") ;// 調用方法進行b1和b2的除法運算,并且將計算結果在控制臺進行輸出System.out.println(b1.divide(b2 , 2 , RoundingMode.UP));}}

小結:后期在進行兩個數的除法運算的時候,我們常常使用的是可以設置取舍模式的divide方法。

7.4 底層存儲方式:

把數據看成字符串,遍歷得到里面的每一個字符,把這些字符在ASCII碼表上的值,都存儲到數組中。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904348.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904348.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904348.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用OMS從MySQL遷移到OceanBase,字符集utf8與utf8mb4的差異

一、問題背景 在一次從MySQL數據庫遷移到OceanBase的MySQL租戶過程中&#xff0c;出現了一個轉換提示&#xff1a; [WARN][CONVER] he table charset:utf8->utf8mb4&#xff0c; 你可能會擔心這種轉換可能導致字符集不兼容的問題。但通過查閱相關資料可知&#xff0c;utf8m…

MATLAB中tabulate函數——先驗概率的簡單估計

load fisheriris X meas(:,1:2); Y species; labels unique(Y); tabulate(Y)ValueCountPercentsetosa5033.33%versicolor5033.33%virginica5033.33%

《Python星球日記》第28天:數據獲取與可視化(綜合項目)

名人說:路漫漫其修遠兮,吾將上下而求索。—— 屈原《離騷》 創作者:Code_流蘇(CSDN)(一個喜歡古詩詞和編程的Coder??) 專欄:《Python星球日記》,限時特價訂閱中ing 目錄 一、項目概述二、數據獲取1. 準備工作2. 使用 `requests` 獲取網頁內容3. 使用 `BeautifulSoup`…

基于深度學習的圖像識別技術:從原理到應用

前言 在當今數字化時代&#xff0c;圖像識別技術已經滲透到我們生活的方方面面&#xff0c;從智能手機的人臉解鎖功能到自動駕駛汽車對交通標志的識別&#xff0c;再到醫療影像診斷中的病變檢測&#xff0c;圖像識別技術正以其強大的功能和廣泛的應用前景&#xff0c;改變著我們…

限免開關實施版本保護措施,保證項目灰度發布安全

迭代用戶限免權限校驗業務 新增限免開關實現普通用戶權益更新&#xff0c;實施版本保護措施&#xff0c;保證項目灰度發布安全&#xff1b; // 是否展示限免標識 func (t *BasePrivilegeService) IsPromotionFree(p consumParams) bool {// 限免開關isFreeUseOpen : p.cfg.Vip…

從 AWS Marketplace 開始使用 AssemblyAI 的語音轉文本模型構建語音智能

語音智能和語音轉文本 &#xff08;STT&#xff09; 技術已變得至關重要&#xff0c;因為組織每天收集數千小時的電話、會議和客戶互動。僅靠原始音頻并不能推動決策 - 組織需要智能來大規模地從語音數據中提取價值。語音智能結合了語音識別、自然語言處理 &#xff08;NLP&…

Android組件化 -> Debug模式下,本地構建module模塊的AAR和APK

本地構建module模塊的AAR gradle.properties isCommonApp false模塊的build.gradle apply plugin: com.android.library&#xff1a;module模塊編譯manifest.srcFile src/main/AndroidManifest.xml&#xff1a;讀取沒有啟動App和Activity的配置文件 if (isCommonApp.toBoo…

FlexibleButton:一個輕巧靈活的按鍵處理庫,讓你的按鍵處理更簡單

在嵌入式系統開發中&#xff0c;按鍵輸入處理是一個常見且重要的環節。然而&#xff0c;許多開發者在處理按鍵時&#xff0c;往往會遇到按鍵消抖、組合按鍵、長按/短按等功能實現的復雜性。如何在保證系統高效運行的同時&#xff0c;簡化按鍵事件的處理呢&#xff1f; 今天&…

探索程序員薪資背后的秘密與未來:智能化工具如何助力職場發展

最新接入DeepSeek-V3模型&#xff0c;點擊下載最新版本InsCode AI IDE 探索程序員薪資背后的秘密與未來&#xff1a;智能化工具如何助力職場發展 引言 在當今數字化時代&#xff0c;程序員作為科技發展的核心力量&#xff0c;其職業前景和薪資水平備受關注。隨著人工智能和自…

【STM32單片機】#14 PWR電源控制

主要參考學習資料&#xff1a; B站江協科技 STM32入門教程-2023版 細致講解 中文字幕 開發資料下載鏈接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 單片機套裝&#xff1a;STM32F103C8T6開發板單片機C6T6核心板 實驗板最小系統板套件科協 目錄 PWR…

第十五屆藍橋杯單片機國賽-串口解析

串口通信像是藍橋杯單片機組國賽中一個若隱若現的秘境&#xff0c;總在不經意間為勇者們敞開大門。然而&#xff0c;初次探索這片領域的冒險者&#xff0c;常常會被其神秘莫測的特性所震懾&#xff0c;黯然退場&#xff08;編不下去了&#xff0c;直接進入正題&#xff09;。 附…

深入探索 51 單片機:從入門到實踐的全面指南

深入探索 51 單片機&#xff1a;從入門到實踐的全面指南 一、引言 在嵌入式系統發展的漫長歷程中&#xff0c;51 單片機猶如一顆璀璨的明星&#xff0c;雖然誕生已有數十年&#xff0c;但至今仍在眾多領域發揮著重要作用。它以結構簡單、易于學習、成本低廉等優勢&#xff0c…

GD32F470+CH395Q

第一步&#xff1a;資料下載 以太網協議棧芯片 CH395 - 南京沁恒微電子股份有限公司 第二步&#xff1a;準備工程 &#xff08;1&#xff09; 首先準備一個編譯無報錯、可以正常打印和延時的工程文件&#xff0c;官方例程采用STM32F1芯片&#xff0c;但本文采用GD32F470芯片 …

Linux 怎么使用局域網內電腦的網絡訪問外部

一次性 export http_proxy"http://192.168.0.188:7890" export https_proxy"http://192.168.0.188:7890"一直生效 寫入 ~/.bashrc&#xff08;或 ~/.bash_profile&#xff09; nano ~/.bashrc加入這一行&#xff1a; export http_proxy"http://19…

Mysql進階篇1_存儲引擎、索引、SQL性能分析指令

文章目錄 1.存儲引擎InnoDBMyISAMMemory存儲引擎選擇和對比 2.索引索引結構索引分類索引語法索引使用&#xff08;建議看完第3節后觀看&#xff09;&#xff01;&#xff01;&#xff01;mysql如何使用索引查詢數據&#xff08;個人理解&#xff09; 3.SQL性能分析SQL執行頻率慢…

LeetCode 熱題 100 118. 楊輝三角

LeetCode 熱題 100 | 118. 楊輝三角 大家好&#xff0c;今天我們來解決一道經典的算法題——楊輝三角。這道題在 LeetCode 上被標記為簡單難度&#xff0c;要求生成楊輝三角的前 numRows 行。楊輝三角是一個經典的組合數學問題&#xff0c;每一行的數字都是其正上方和正左上方…

修改或禁用Cursor的全局搜索默認快捷鍵

在 Cursor 中&#xff0c;默認情況下 雙擊 Shift 會打開 全局搜索&#xff08;Quick Open&#xff09;&#xff0c;類似于 VS Code 的 CtrlP 功能。如果你想修改或禁用這個快捷鍵&#xff0c;可以按照以下步驟操作&#xff1a; 1. 打開快捷鍵設置 方法 1&#xff1a;按下 Ctrl…

HarmonyOS Device Connector(hdc)

它是為開發人員提供的用于調試的命令行工具&#xff0c;通過該工具可以在windows/linux/mac系統上與設備進行交互。 hdc分為三部分&#xff1a; client&#xff1a;運行在電腦端的進程&#xff0c;開發者在執行hdc命令時啟動該進程&#xff0c;命令結束后進程退出。 server&…

開源PDF解析工具Marker深度解析

開源PDF解析工具Marker深度解析 檢索增強生成&#xff08;RAG&#xff09;系統的第一步就是做 pdf 解析&#xff0c;從復雜多樣的 pdf 中提取出干凈準確的文本內容。現有的最優秀的開源工具有兩個&#xff1a;Marker 和 MinerU。因為 Marker 是個人開發者做的&#xff0c;文檔…

ARM子程序調用與返回

子程序&#xff08;也叫過程、函數、方法&#xff09;是一個能被調用和執行并返回到調用點那條指令的代碼 段。 兩個問題&#xff1a;如何將參數傳遞給子程序或從子程序中傳遞出來&#xff1f;怎么從子程序返回到調用點&#xff1f; 指令BSR Proc_A調用子程序Proc_A。 處理器將…