常用類(1):Object類
常用類:Object
一、API概述(Application Programming Interface)
應用程式程式設計介面
編寫一個機器人程式去控制機器人踢足球,程式就需要向機器人發出向前跑、向後跑、射門、
搶球等各種命令,沒有編過程式的人很難想象這樣的程式如何編寫。但是對於有經驗的開發人員來說,
知道機器人廠商一定會提供一些用於控制機器人的Java類,這些類中定義好了操作機器人各種
動作的方法。其實,這些Java類就是機器人廠商提供給應用程式程式設計的介面,
大家把這些類稱為Xxx Robot API。
本章涉及的Java API指的就是JDK中提供的各種功能的Java類。
二、常用類
Object類/Scanner類
String類/StringBuffer類/StringBuilder類
陣列高階和Arrays類
基本型別包裝類(Integer,Character)
正則表示式(Pattern,Matcher)
Math類/Random類/System類
BigInteger類/BigDecimal類
Date類/DateFormat類/Calendar類
三、Object類概述及其類中的方法
1、Object類概述
Class Object是類Object結構的根; 每個班都有Object作為超類; 所有物件(包括陣列)都實現了這個類的方法; 每個類都直接或者間接的繼承Object類 例:隨便寫個類,都預設繼承Object類 public class Student extends Object{ }
2、學習Object中的一個方法:雜湊演算法
public int hashCode()返回物件的雜湊碼值
注意:這裡的雜湊碼值是根據雜湊演算法計算出來的一個值,這個值和地址有關係,
但是並不是實際的地址值。簡單理解為地址值的另一種表現形式
案例:
//建立一個class檔案,定義一個類 public class Student extends Object{ } //同一個包下再建立一個class檔案,定義一個類 public class StudentTest { public static void main(String[] args) { //因為在一個包內,所以能建立Student物件 Student s = new Student(); //呼叫Object中的hashCode方法 System.out.println(s.hashCode()); //再建立一個Student物件 Student s1 = new Student(); System.out.println(s1.hashCode()); } } 執行結果如下: 356573597 1735600054 Process finished with exit code 0 //結論:呼叫hashCode方法時,輸出的雜湊碼值不一定相同
3、學習Object中的一個方法:getClass
public final 類 getClass()
返回此Object的執行時類
返回的類物件是被表示類的static synchronized方法鎖定的物件
案例:
public class StudentTest {
public static void main(String[] args) {
//建立一個Student物件
Student s = new Student();
System.out.println(s.getClass());
}
}
執行結果如下:
class myself.day18.Student
Process finished with exit code 0
//輸出的是當前專案下一個相對路徑的class型別
4、學習Object類中的一個方法:toSring
//建立一個Student2的類
public class Student2 {
//定義成員變數
private String name;
private int age;
//無參構造方法
Student2(){
}
//帶參構造方法
Student2(String name,int age){
this.name = name;
this.age = age;
}
//定義公共的setXxx()和getXxx()方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
public class StudentTest2 {
public static void main(String[] args) {
//建立Student2物件
Student2 s2 = new Student2();
System.out.println(s2.toString());//myself.day18.Student2@1540e19d
//System.out.println(s2.getClass().getName());//myself.day18.Student2
}
}
執行結果如下:
myself.day18.Student2@1540e19d
Process finished with exit code 0
/*
s2.toString()在s2.getClass().getName()基礎上多了@1540e19d
根據toString方法說明:
getClass().getName() + '@' + Integer.toHexString(hashCode())
可知:
Integer類中有一個toHexString方法將雜湊值轉換成地址值
*/
查詢Integer類中的toHexString方法
Integer類中有一個toHexString方法將雜湊值轉換成地址值
public static String toHexString(int i)
返回整數引數的字串表示形式,作為16位中的無符號整數
因此可知:
System.out.println(s.toString());
等價於
System.out.println(s.getClass().getName()+"@"+Integer.toHexString(s.hashCode()));
我們雖然掌握了toString()的方法使用,但是呢列印的結果是一個地址值,拿到地址值是沒有意義的
我們正常列印一個物件,其實是想看該物件中的成員變數的值。
又因為toString()方法的返回值是String型別,並且屬於Object類中的
而Object類是所有類的父類,那麼我們自己定義類的時候,就可以重寫該方法,重寫裡面的實現。
將來呼叫toString()方法的時候,嚴格遵循編譯看左,執行看右,所以呼叫的是重寫後的方法。
在Student2中重寫toString方法
.......(方便觀看,上方省略)
public int getAge() {
return age;
}
//重寫toString方法
@Override
public String toString() {
// return super.toString();
return "姓名:" + name + "年齡:" + age;
}
}
重寫以後再返回StudentTest2類中,再次執行一下
public class StudentTest2 {
public static void main(String[] args) {
//建立Student2物件
Student2 s2 = new Student2();
System.out.println(s2.toString());
}
}
執行結果為:
姓名:null年齡:0
Process finished with exit code 0
賦值一下
public class StudentTest2 {
public static void main(String[] args) {
//建立Student2物件
Student2 s2 = new Student2();
System.out.println(s2.toString());
//賦值
s2.setName("偉爺");
s2.setAge(18);
System.out.println(s2.toString());
}
}
執行結果為:
姓名:null年齡:0
姓名:偉爺年齡:18
Process finished with exit code 0
5、類最終寫法的誕生
通過上述案例,誕生了類的最終寫法
類最終寫法:4.0版本:
成員變數:private
構造方法:無參,有參
成員方法:getXxx()和setXxx(),有特有方法就加上特有方法
toString():自動生成即可 快捷鍵 Alt+Insert回車
最終版本案例:
class Student2 {
//定義成員變數
private String name;
private int age;
//無參構造方法
Student2(){
}
//帶參構造方法
Student2(String name,int age){
this.name = name;
this.age = age;
}
//定義公共的setXxx()和getXxx()方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//重寫方法
//Alt+Insert回車,選擇toString()方法,回車再回車
@Override
public String toString() {
return "Student2{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class StudentTest2 {
public static void main(String[] args) {
//建立Student2物件
Student2 s2 = new Student2();
//賦值
s2.setName("偉爺");
s2.setAge(18);
System.out.println(s2.toString());
}
}
執行結果為:
Student2{name='偉爺', age=18}
Process finished with exit code 0
toString方法總結
如果子類中(學生類)不重寫toString,在測試類中,通過物件呼叫該方法,打印出的是地址值;
重寫之後再呼叫toString,打印出的就是規範的成員變數值
6、學習Object類中的一個方法:equals
public boolean equals(Object obj)指示一些其他物件是否等於此
==:
比較基本型別:比較的是值是否相同
比較引用型別:比較的地址值是否相同
equals:
比較的是引用資料型別
案例:
public class Student3 {
//定義成員變數
private String name;
private int age;
//無參構造方法
Student3(){
}
//帶參構造方法
Student3(String name,int age){
this.name = name;
this.age = age;
}
//定義公共的setXxx()和getXxx()方法
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
//重寫toString()
@Override
public String toString() {
return "Student3{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class StudentTest3{
public static void main(String[] args) {
Student3 s3 = new Student3("偉爺",18);
Student3 s4 = new Student3("偉爺",18);
System.out.println(s3==s4);//比較的是地址值是否相同:false
Student3 s5 =s3;//將物件s3賦值給s5物件
System.out.println(s5==s3);//true
//用epuals比較引用資料型別
System.out.println(s3.equals(s4));//比較的是地址值是否相同:false
System.out.println(s3.equals(s5));//比較的是地址值是否相同:true
System.out.println(s3.equals(s3));//比較的是地址值是否相同:true
}
}
我們只知道equals是用來比較引用資料型別的,但是我們卻不知道是內部是如何實現的;
如果想要弄明白一個類中的方法是如何實現的時候,API也沒告訴我們怎麼辦呢?
看原始碼。將滑鼠游標放在方法名上 ctrl+滑鼠左鍵
以 System.out.println(s3.equals(s4));為例
ctrl+滑鼠左鍵
會出現下面程式碼:
public boolean equals(Object obj) {
return (this == obj);
}
分析可知:this指的s3,obj指的是s4
通過觀察原始碼發現:Object類中的equals方法,底層的實現依舊是 ==
而 == 比較引用資料型別比較的是地址值,當地址值不一樣的時候返回的是false
由上可知,比較的都是地址值
如果我們想要比較兩個物件的成員變數值,該怎麼做呢?
由public boolean equals(Object obj)可知,equals是被public修飾的
想要在測試類中比較物件的成員變數值,在學生類中需要重寫equals方法
(不需要我們自己重寫,快捷鍵 Alt+Insert回車 自動生成即可)
重寫equals方法後,再回到測試類。再次執行,呼叫equals比較的就是成員變數值了
public class StudentTest3{
public static void main(String[] args) {
Student3 s3 = new Student3("偉爺",18);
Student3 s4 = new Student3("偉爺",18);
System.out.println(s3==s4);//比較的是地址值是否相同:false
Student3 s5 =s3;//將物件s3賦值給s5物件
System.out.println(s5==s3);//true
//用epuals比較引用資料型別
System.out.println(s3.equals(s4));//比較的是地址值是否相同:true
System.out.println(s3.equals(s5));//比較的是地址值是否相同:true
System.out.println(s3.equals(s3));//比較的是地址值是否相同:true
}
}
equals方法總結:
如果子類中(學生類)不重寫equals方法,預設呼叫的是Object類中的equals方法,預設比較的是地址值;
重寫equals方法之後,比較的是物件成員變數值
7、學習Object類中的一個方法:clone
protected Object clone()
建立並返回此物件的副本
未重寫clone方法之前,呼叫該方法的時候會直接報錯,所以要先在子類(學生類)中重寫克隆方法
重寫該方法與重寫其他方法有點區別,該方法需要通過子類super去呼叫,不能使用Alt+Inset快捷鍵
//重寫clone方法。否則無法呼叫
//通過子類super去呼叫(重寫該方法不能使用Alt+Inset快捷鍵)
//輸入c,然後根據提示選擇protected Object clone() {...}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
重寫clone方法後,再次回到測試類來呼叫該方法
由上可知,重寫clone方法後,在測試類呼叫該方法後,列印輸出的時候,還是會報錯;
這說明並不是什麼樣的類都可以被克隆,類需要滿足一個標記才能被克隆
類該怎麼去標記?
在工具說明書中:
clone的方法Object執行特定的克隆操作。
首先,如果此物件的類不實現介面Cloneable ,則丟擲CloneNotSupportedException
將想要呼叫克隆方法的類實現Cloneable介面
通過觀察API發現,Cloneable介面中沒有成員變數也沒有成員方法
今後看到類似於Cloneable接口裡面什麼都沒有的介面,我們稱之為標記介面
標記介面,只需在類名後面加implements Cloneable即可,表示實現介面
Public class Student4 implements Cloneable{
//定義成員變數
private String name;
private int age;
//無參構造方法
Student4(){
}
//帶參構造方法
Student4(String name,int age){
this.name = name;
this.age = age;
}
//定義公共的setXxx()和getXxx()方法
...(為了方便觀看,暫且省略)
新增指標後,回到測試類再次執行
由上可知,通過呼叫克隆方法,輸出的結果會打印出一模一樣的。
我們可以發現,通過再次建立物件,再次賦值,也可以打印出一模一樣的結果,那麼克隆的意義在哪?
答:當二次賦值的時候,再輸出,結果與第一次是不一樣的;
但是用克隆輸出的時候,無論前面再怎麼賦值,打印出的結果都是和第一次一樣的
拷貝在IT行業中常見兩種:
淺拷貝
拷貝的時候,重新建立一個物件,成員變數值和被拷貝的一樣,但是後續修改與原先的沒有關係
深拷貝
拷貝的時候,沒有建立新的物件,只是改個名字,地址值都一樣,修改拷貝後的連帶影響到原先的
8、學習Object類中的一個方法:finalize
protected void finalize()
throws Throwable當垃圾收集確定不再有對該物件的引用時,
垃圾收集器在物件上呼叫該物件。
一個子類覆蓋了處理系統資源或執行其他清理的finalize方法。
這個方法簡單理解為就是用來垃圾回收的,什麼時候回收呢?不確定。
具體情況下什麼時候回收呢?自行上網瞭解GC機制(面試會問道)