Java基础知识回顾之Object类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_18948359/article/details/84799687

简介

类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元。
	}
}

猜你喜欢

转载自blog.csdn.net/qq_18948359/article/details/84799687
今日推荐