简介
类Object是类层次结构的根类。每个类都使用Object作为超类。所有对象(包括数组)都实现这个类的所有方法。我们接触到的元素有:对象、数组、接口等,这么多的元素为了方便统一,就可以使用 Object。
任何一个类在定义的时候如果没有明确的继承一个父类的话,那么他就是Object类的子类。
public class TestDemo {
}
// 等价于:
public class TestDemo extends Object{
}
当我们看官方文档时,会发现 Object 类会有一个无参的构造方法。这个是因为:Object 类是所有类的父类,那么所有类的对象实例化的时候,子类构造方法一定要默认调用父类的无参构造。
Object类的常用方法
从严格意义上面来(一般不遵守)说,任何一个简单的Java类都应该覆写 Object 类中的以下方法:
- 获取对象信息:
public String toString();
- 对象比较:
public boolean equals(Object object)
- 取得对象 HASH 码:
public int hashCode()
toString()
如果是一个 String 类的对象,直接输出这个对象可以获取到字符串的内容,但是输出一个自定义的对象,就一个对象编码。
public class TestDemo {
public static void main(String[] args) {
String str = "Object字符串";
TestDemo ts = new TestDemo();
System.out.println(str); // Object字符串
// 当我们在输出对象的时候,会自动调用对象中的 toString() 方法将对象变为字符串之后再输出。
System.out.println(ts); // TestDemo@340f438e
System.out.println(ts.toString()); // TestDemo@340f438e
}
}
当我们看 Object 类的源码的时候会发现 toString() 方法如下:
/*
返回该对象的字符串表示,非常重要的方法
getClass().getName();获取字节码文件的对应全路径名例如java.lang.Object
Integer.toHexString(hashCode());将哈希值转成16进制数格式的字符串。
*/
public String toString(){
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
但是我们发现 String类 的 toString() 方法输出的结果不一样,我们打开 String 类的方法,可以看到 String 类是将 toString() 方法重写了:
/**
* This object (which is already a string!) is itself returned.
*
* @return the string itself.
*/
public String toString() {
return this;
}
equals() 方法
我们打开 Object 类的源码, 可以看到 equals() 方法其实比较的是比较对象的地址。
/*
* @param obj the reference object with which to compare.
* @return {@code true} if this object is the same as the obj
* argument; {@code false} otherwise.
* @see #hashCode()
* @see java.util.HashMap
*/
public boolean equals(Object obj) {
return (this == obj);
}
但是我们发现 String 类比较的是 值的信息,所以我们打开看下 String类的源码,发现 String 重写了equals() 方法
/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*
* @param anObject
* The object to compare this {@code String} against
*
* @return {@code true} if the given object represents a {@code String}
* equivalent to this string, {@code false} otherwise
*
* @see #compareTo(String)
* @see #equalsIgnoreCase(String)
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
hashCode() 方法
散列码(hashCode)是按照一定的算法由对象得到的一个数值,散列码没有规律。如果 A 和 B 是不同的对象,A.hashCode() 与 B.hashCode() 基本上不会相同。
从源码上看:
/*
hashCode的常规协定是:
1.在java应用程序执行期间,在对同一对象多次调用hashCode()方法时,必须一致地返回相同的整数,
前提是将对象进行equals比较时所用的信息没有被修改。
从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
2.如果根据equals(object)方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode方法都必须生成相同的整数结果。
3.如果根据equals(java.lang.Object)方法,两个对象不相等,
那么对这两个对象中的任一对象上调用hashCode()方法不要求一定生成不同的整数结果。
但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
*/
public native int hashCode();
实例
接收数组数据
public class TestDemo {
public static void main(String[] args) {
Object obj = new int[]{1, 2, 3}; // 向上转型
System.out.println(obj); // [I@15db9742 对象地址前面有一个 [ , 表示为数组
if( obj instanceof int[] ){ // 判断是否为 数组对象
int data[] = (int[]) obj;
for (int i = 0; i < data.length; i++) {
System.out.println(data[i]);
}
}
}
}
接收接口对象
interface A{
public void fun();
}
class B extends Object implements A{
@Override
public void fun() {
System.out.println("接口实现类");
}
}
public class TestDemo {
public static void main(String[] args) {
A a = new B(); // 接口对象
Object obj = a; // 接收接口对象
A t = (A) obj; // 使用强制转换向下转型
t.fun(); // 输出结果:接口实现类
}
}
对象克隆
对象克隆指的是对象的复制操作,进行克隆了之后的对象是另外一个对象,指向的内存地址是不一样的,在 Object 类中提供有一个专门的克隆方法。定义如下:
protected native Object clone() throws CloneNotSupportedException;
会抛出一个 CloneNotSupportedException 的异常,但是我们通过源码查看 Cloneable 发现其定义是: public interface Cloneable { }
,是一个空的接口,所以接口为标识接口。
// 实现 Cloneable 标识接口
class Book implements Cloneable{
private String title;
private double price;
public Book(String title, double price) {
this.title = title;
this.price = price;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public String toString() {
return "书名《" + this.title + "》价格:" + this.price + "元。";
}
/**
* 由于需要调用 protect 方法(本包、不同包的子类调用)
* 所以直接覆写 Object 类中的 clone 方法
*/
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class SystemTest {
public static void main(String[] args) throws Exception {
Book booka = new Book("Java开发", 88.6);
Book bookb = (Book) booka.clone();
// 给 clone 的类修改内容
bookb.setTitle("Android开发");
System.out.println(booka); // 书名《Java开发》价格:88.6元。
System.out.println(bookb); // 书名《Android开发》价格:88.6元。
}
}