Object類用於統一對象、數組和接口。
Object類基本描述
1、Object
類是所有類的父類,即任何一個類在沒有定義繼承某個類時,Object類就是其父類。
class Book{}
class Book extends Object{}
上述兩個類聲明是等價的,Object類是唯一沒有父類的類。Object類是所有類的父類,因此可以利用Object類通過向上轉型,接收所有類型的對象。
class Book extends Object {
}
public class Demo {
public static void main(String[] args) {
Object objA = new Book(); // 向上轉型
Object objB = "Hello"; // 向上轉型
Book b = (Book) objA; // 向下轉型
String s = (String) objB; // 向下轉型
}
}
因此在不確定參數類型時,使用Object類型是最好的選擇。
2、Object類中定義了一個無參構造方法,因爲其是所有類的父類,所以實例化子類對象時必然會調用父類的無參構造方法。
一般而言,定義簡單Java類時應覆寫Object類中的如下方法:
· 取得對象信息:public String toString();
· 對象比較:public boolean equals(Object obj);
· 取得對象HASH碼:public int hashCode();
toString()
class Book extends Object {
}
public class Demo {
public static void main(String[] args) {
Book b = new Book();
String s = "Hello";
System.out.println(b); // Book@1540e19d
System.out.println(b.toString()); // Book@1540e19d
System.out.println(s); // Hello
}
}
上述代碼中直接輸出實例對象和使用toString()輸出的結果是一樣。因爲輸出對象時,會自動調用toString()將對象變爲字符串後輸出。Object類中的toString()
爲了適應對象的輸出,僅輸出對象的編碼。
但是這和我們的想法不符,我們想輸出的應該是實例化對象的屬性信息,因此要覆寫toString()。
範例:覆寫toString()
class Book extends Object {
private String title;
private double price;
// getter,setter,無參構造方法暫時略
public Book(String title, double price) {
this.title = title;
this.price = price;
}
public String toString() {
return "書名:" + this.title + ",價格:" + this.price;
}
}
public class Demo {
public static void main(String[] args) {
Book b = new Book("Java開發", 20.3);
System.out.println(b); // 書名:Java開發,價格:20.3
}
}
此時直接輸出對象,調用的就是覆寫後的方法。
equals()
範例:對象比較
class Book extends Object {
private String title;
private double price;
// getter,setter,無參構造方法暫時略
public Book(String title, double price) {
this.title = title;
this.price = price;
}
public String toString() {
return "書名:" + this.title + ",價格:" + this.price;
}
public boolean equals(Object obj) {
if (this == obj) { // 地址相同
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Book)) { // 不是Book類對象
return false;
}
Book book = (Book) obj;
if (this.title.equals(book.title)
&& this.price == book.price) {
return true;
}
return false;
}
}
public class Demo {
public static void main(String[] args) {
Book bA = new Book("Java開發", 20.3);
Book bB = new Book("Java開發", 20.3);
System.out.println(bA.equals(bB)); // true
System.out.println(bA.equals("Hello")); // false
}
}
覆寫後的equals()用於進行對象比較。
Object接收引用類型
1、Object類是所有類的父類,因此Object類對象可以接收所有類型的對象,包括數組和接口對象。
範例:接收數組數據
public class Demo {
public static void main(String[] args) {
Object obj = new int[]{1, 2, 3};
System.out.println(obj); // [I@1540e19d表示數組
if (obj instanceof int[]) { // 如果是數組,則輸出
int data[] = (int[]) obj; // 向下轉型
for (int x = 0; x < data.length; x++) {
System.out.println(data[x]);
}
}
}
}
範例:接收接口對象
interface A {
public void fun();
}
class B implements A {
public void fun() {
System.out.println("Hello");
}
}
public class Demo {
public static void main(String[] args) {
A a = new B();
Object obj = a;
A t = (A) obj;
t.fun(); // Hello
}
}
上述代碼把參數類型統一爲Object
,有利於開發。
Object修改鏈表
此時我們可以利用Object類的特點解決之前開發的鏈表存在的問題:由於參數類型不統一,每次使用都要進行重新開發。
範例:修改鏈表
class Link { // 鏈表類,外部可見
private class Node { // 節點類
private Object data; // 保存數據
private Node next; // 引用關係
public Node(Object data) { // 有數據纔有Node
this.data = data;
}
// 設置關係
public void addNode(Node newNode) {
if (this.next == null) {
this.next = newNode;
} else {
this.next.addNode(newNode);
}
}
// 數據查詢
public boolean containsNode(Object data) {
if (data.equals(this.data)) { // 當前數據等於要目標數據
return true; // 結束查詢
} else { // 當前數據不等於目標數據
if (this.next != null) { // 有後續節點
return this.next.containsNode(data);
} else { // 沒有後續節點
return false;
}
}
}
public Object getNode(int index) {
// 當前foot內容與要查詢的索引比較
// foot自增,目的是下次查詢方便
if (Link.this.foot++ == index) {
return this.data;
} else {
return this.next.getNode(index);
}
}
// 修改節點信息
public void setNode(int index, Object data) {
if (Link.this.foot++ == index) {
this.data = data;
} else {
this.next.setNode(index, data);
}
}
// 刪除非根節點
public void removeNode(Node previous, Object data) {
// 參數中傳遞上一個節點和要刪除的數據
if (data.equals(this.data)) {
previous.next = this.next;
} else {
this.next.removeNode(this, data);
}
}
public void toArrayNode() {
Link.this.retArray[Link.this.foot++] = this.data;
if (this.next != null) {
this.next.toArrayNode();
}
}
}
// ====================以上爲內部類=====================
private Node root; // 根節點
private int count = 0; // 節點的個數
private int foot = 0; // 索引
private Object[] retArray; // 返回的數組
public void add(Object data) {
if (data == null) { // 輸入數據爲空
return;
}
Node newNode = new Node(data); // 要保存的數據
if (this.root == null) { // 根節點不存在
this.root = newNode; // 設爲根節點
} else { // 根節點存在,交由Node處理
this.root.addNode(newNode);
}
this.count++; // 每次增加節點,count+1
}
// 獲取鏈表長度
public int size() {
return this.count;
}
// 判斷是否爲空鏈表
public boolean isEmpty() {
return this.count == 0;
}
// 判斷數據是否存在
public boolean contains(Object data) {
if (data == null || root == null) {
return false;
}
return this.root.containsNode(data);
}
// 根據索引獲取信息
public Object get(int index) {
if (index > this.count) { // 超出查詢範圍
return null;
}
this.foot = 0;
return this.root.getNode(index); // 查詢交給Node類
}
// 設置信息
public void set(int index, Object data) {
if (index > this.count) {
return;
}
this.foot = 0; // 重置foot,作爲索引
this.root.setNode(index, data); // Node進行修改數據
}
// 判斷刪除節點是否爲root
public void remove(Object data) {
if (this.contains(data)) { // 判斷數據是否存在
if (data.equals(this.root.data)) { // 判斷數據是否是root數據
this.root = this.root.next;
} else {
// root是Node對象,此處直接訪問內部類私有操作
this.root.next.removeNode(this.root, data);
}
this.count--; // 刪除後數據個數減少
}
}
public Object[] toArray() {
if (this.root == null) {
return null;
}
this.foot = 0; // 需要腳標控制
this.retArray = new Object[this.count]; // 根據保存內容開闢數組
this.root.toArrayNode();
return this.retArray;
}
}
範例: 測試程序
public class Demo {
public static void main(String[] args) {
Link all = new Link();
all.add("A");
all.add("B");
all.add("C");
System.out.println(all.size());
all.remove("B");
Object[] data = all.toArray();
for (int x = 0; x < data.length; x++) {
String str = (String) data[x];
System.out.println(str);
}
}
}
綜合實戰: 寵物商店
要求: 以程序結構爲主,實現一個寵物商店的模型,具有保存多個寵物的信息(名字,年齡),寵物上架、下架、模糊查詢功能。
思路圖:
寵物商店的商品(寵物)要符合寵物這一標準(接口),寵物商店藉助鏈表實現上架、下架和模糊查詢功能。
範例:定義寵物的標準
interface Pet { // 定義寵物的標準
public String getName();
public int getAge();
}
寵物商店與具體的寵物無關,只和寵物這一接口有聯繫。
範例:定義寵物商店
class PetShop {
private Link pets = new Link(); // 要保存的寵物信息
public void add(Pet pet) { // 上架
this.pets.add(pet);
}
public void delete(Pet pet) { // 下架
this.pets.remove(pet);
}
public Link search(String keyWord) { // 模糊查詢,返回的內容個數不明
Link result = new Link();
// 將集合以數組的形式返回,
// 真正要查詢的數據是Pet接口對象的getName()的返回值
Object obj[] = this.pets.toArray();
for (int x = 0; x < obj.length; x++) {
Pet p = (Pet) obj[x];
if (p.getName().contains(keyWord)) {
result.add(p);
}
}
return result;
}
}
範例: 定義貓類
class Cat implements Pet {
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Cat)) {
return false;
}
Cat cat = (Cat) obj;
if (this.name.equals(cat.name)
&& this.age == cat.age) {
return true;
}
return false;
}
public String toString() {
return "貓名:" + this.name + ", 年齡" + this.age;
}
}
可參照上述結構,定義一個狗類。
範例:測試
public class Demo {
public static void main(String[] args) {
PetShop shop = new PetShop();
shop.add(new Cat("阿貓", 9));
shop.add(new Cat("貓咪", 19));
shop.add(new Dog("阿狗", 10));
shop.add(new Dog("狗子", 8));
// 模糊查詢
Link all = shop.search("阿");
Object obj[] = all.toArray();
for (int x = 0; x < obj.length; x++) {
System.out.println(obj[x]);
}
shop.delete(new Dog("狗子", 8));
}
}