JAVA中所有类的祖先-Object类源码解读

Object类是Java中所有类的祖先,在Java中每个类都是由它拓展而来,我们都知道继承一个类的写法

class child extends father

但是继承Object类并不需要写

class child extends Object

因为如果你不明确指定继承的类,Object就被默认为是这个类的父类。
由于在Java中,每个类都是由Object类拓展而来的,所以熟悉这个类所提供的服务就有必要认真的去观摩观摩了。
1、Equals方法
在Objdect类中的equals方法用于检测一个对象是否等于另外的一个对象,如果两个对象具有相同的引用,则相等。下面用一个例子来解读。

class Employee
{
	public Employee(String name,double salary,int year,int month,int day) {
	this.name = name;
	this.salary = salary;
	GregorianCalendar calendar = new GregorianCalendar(year,month-1,day);
	this.hireDay =calendar.getTime(); 
	}
	
	public String getName()
	{
		return this.name;
	}
	
	public double getSalary()
	{
		return this.salary;
	}
	
	public Date getHireDay()
	{
		return this.hireDay;
	}

	
	public void raiseSalary(double byPercent)
	{
		double raise = salary * byPercent / 100;
		salary += raise;
	}
	
	public boolean equals(Object otherObject)
	{
		if(this==otherObject)return true;
		if(otherObject==null)return false;
		if(getClass()!=otherObject.getClass())return false;
		Employee other = (Employee)otherObject;
		return this.name.equals(other.name)&&this.salary==other.salary&&this.hireDay.equals(other.hireDay);
	}
	
	public int hashCode()

	{
		return 7*name.hashCode()+11*new Double(salary).hashCode()+13*hireDay.hashCode();
	}
	
	/*public String toString()
	{
		return getClass().getName()+"[name="+name+",salary="+salary+",hireDay"+hireDay+"]";
	}*/
	
	private String name;
	private double salary;
	private Date hireDay;
}

class Manage extends Employee
{
	public Manage(String name,double salary,int year,int month,int day)
	{
		super(name,salary,year,month,day);
		this.bonus = 0;
	}
	
	public double getSalary()
	{
		
		double baseSalary = super.getSalary();
		return baseSalary+bonus;
	}
	
	public void setBonus(double b)
	{
		bonus = b;
	}
	
	public boolean equals(Object otherObject)
	{
		if(!super.equals(otherObject))return true;
		Manage other = (Manage)otherObject;
		return bonus == other.bonus;
	}
	
	public int hashCode()
	{
		return super.hashCode()+17*new Double(bonus).hashCode();
	}
	
	/*public String toString()
	{
		return super.toString()+"[bonus="+bonus+"]";
	}*/
	
	private double bonus;

}

这里定义了两个类,一个Employee类和一个子类Manage类,当我们创建两个对象的时候

Employee alice1 = new Employee("Alice Adams",75000,1987,12,15);
Employee Bob = new Employee("Bob",50000,1989,1,25);
System.out.println("alice1.equals(alice3):"+alice1.equals(alice3));
System.out.println("alice1.equals(Bob):"+alice1.equals(Bob));
...
alice1.equals(alice3):true
alice1.equals(Bob):false

1)可以看到输出的结果alice1和alice指向的是同一个引用,所以结果是对的,而alice1和Bob指向的不是同一个对象,所以不相等。
2)当遇到的参数不属于同一个类的时候equals应该怎么做呢?比如在Employee和Manage对象中都有相同的姓名、薪水和雇佣日期。我们可以这样定义equals

public boolean equals(Object otherObject)
	{
		if(this==otherObject)return true;//检测this和otherObeject引用的是否同一个对象
		if(otherObject==null)return false;//检测otherObject是否为空
		if(getClass()!=otherObject.getClass())return false;//比较this和otheObject是否是同一个类的
		Employee other = (Employee)otherObject;//将otherObject转换成为响应的类的类型变量
		return this.name.equals(other.name)&&this.salary==other.salary&&this.hireDay.equals(other.hireDay);//开始做字段的匹配
	}



//如果在子类中重新定义equals,就要在其中包含调用super.equals(other)
	public boolean equals(Object otherObject)
	{
		if(!super.equals(otherObject))return true;
		Manage other = (Manage)otherObject;
		return bonus == other.bonus;
	}
	

equals和“==”的区别

==是判断两个变量或实例是不是指向同一个内存空间
equals是判断两个变量或实例所指向的内存空间的值是不是相同

当这两者除了在String类型和封装器上的比较有区别,其他并没有区别,因为String类型重写了equals
String下的equals源码:
在这里插入图片描述所以在这里面,equals()指比较字符串或封装对象对应的原始值是否相等,"=="是比较两个对象是否为同一个对象。

StringBuilder sb1 = new StringBuilder("aaa");
StringBuilder sb2 = new StringBuilder("aaa");
System.out.println(sb1.equals(sb2)+" "+ (sb1==sb2));//输出false false,因为是对象的比较,equals和“==”都是比较引用
String sb1 = new String("aaa");
String sb2 = new String("aaa");
System.out.println(sb1.equals(sb2)+" "+ (sb1==sb2));//输出 true false.因为String重写了equals,equals比较的是值。

2、HashCode方法
HashCode是由对象导出的一个整型值,(散列码是由内容导出的)如果x和y 是不同的对象,则他们的散列值一般是不同的。
在Object类中的hashCode方法默认导出的是对象的存储地址。
另Equals和hashCode的定义必须一致,如果x.equals(y)返回true,那么x和y的hashCode应该具有相同的值。
比如:
StringBuilder sb1 = new StringBuilder(“aaa”);
StringBuilder sb2 = new StringBuilder(“aaa”);
System.out.println(sb1.equals(sb2)+" "+ (sb1==sb2));

	System.out.println("alice1.hashCode():"+alice1.hashCode());	 
        System.out.println("alice3.hashCode():"+alice3.hashCode());
	public int hashCode()

	{
		return 7*name.hashCode()+11*new Double(salary).hashCode()+13*hireDay.hashCode();//与equals有同样的字段进行计算,计算规则自定义,但是应该让散列码更均匀
	}
//输出结果
alice1.hashCode():377780067
alice3.hashCode():377780067
//如果我们将上面的方法给注释了,则返回的是存储地址的值
alice1.hashCode():1028566121
alice3.hashCode():1118140819

3、toString方法***
在Object中还有一个很重要的方法就是toString方法。它用于返回表示对象值得字符串。在Object中我们可以看到它是这样定义的

 /**
     * Returns a string representation of the object. In general, the
     * {@code toString} method returns a string that
     * "textually represents" this object. The result should
     * be a concise but informative representation that is easy for a
     * person to read.
     * It is recommended that all subclasses override this method.
     * <p>
     * The {@code toString} method for class {@code Object}
     * returns a string consisting of the name of the class of which the
     * object is an instance, the at-sign character `{@code @}', and
     * the unsigned hexadecimal representation of the hash code of the
     * object. In other words, this method returns a string equal to the
     * value of:
     * <blockquote>
     * <pre>
     * getClass().getName() + '@' + Integer.toHexString(hashCode())
     * </pre></blockquote>
     *
     * @return  a string representation of the object.
     */
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
alice1=alice2:Employee@3d4eac69,Employee@3d4eac69
alice1=alice3:Employee@3d4eac69,Employee@42a57993

它返回的是一个类名和散列码,但是返回这个值有点太抽象,对我们的意义并不是很大,我们可以对这个方法进行重载,返回我们想要的字段

public String toString()
	{
		return getClass().getName()+"[name="+name+",salary="+salary+",hireDay"+hireDay+"]";
	}/**/
//输出结果
alice1=alice2:Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987],Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987]
alice1=alice3:Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987],Employee[name=Alice Adams,salary=75000.0,hireDayTue Dec 15 00:00:00 CST 1987]

对于数组类型的域,equals、hashcode和都可以应用静态的Arrays调用来检测。
4、class getClass()
返回包含对象信息的类的对象,
5、protected native Object clone()
拷贝与克隆的区别
在这里插入图片描述拷贝:拷贝的变量与原变量指向同一个对象

Employee original = new Employee("John Public",50000);
Employee copy = original;
copy.raiseSalary(10);//则原始的original的Salary也会改变

克隆:创建一个对象的副本。Java运行时系统将为新实例分配存储控制,并不是只创建一个变量指向相同的空间哦,而是有开辟新的存储空间。

Employee copy = original.clone();
copy.raiseSalary(10);//original的salary并没有改变

但是事情并没有那么简单,clone是一个Proteced方法,也就是说用户编写的代码不能直接访问,如果对象中的所有数据域都属于基本数值或基本类型,则不会出现什么情况,但是如果对象中包含对子对象的引用,则克隆结果会使两个域引用同一个子对象,

在这里插入图片描述
所以针对这种情况,我们要对clone进行重定义,将其定义为public类型。

class Employee implements Cloneable()
{
	public Employee clone() throws CloneNotSupportedException
	{
			Employee cloned = (Employee)super.clone();
			cloned.hireDay = (Date)hireDay.clone();//所有可变的域都应该克隆
			return cloned;
	}	
}

6、void notify(),voide notifyall(),void wait(long timeout)
这三者一般应用在同步synchronized关键字声明的方法中,如果一个方法用synchronized关键字声明后,那么对象的锁将保护整个方法

public synchronized void method()
{
method body
}

而wait 和notify,notifyall用在这个方法中。

void wait(long timeout): 导致线程进入等待状态知道它被通知,该方法只能在一个同步方法中调用。如果当前线程不是对象锁的持有者,该方法抛出一个IllegalMonitorStatwException异常
voide notifyall():解除那些在该对象上调用wait方法的线程的阻塞状态,该方法只能在同步方法或同步块内部调用,如果当前线程不是对象锁的持有者,则抛出IllegalMonitorStatwException异常
voide notify():随机选择一个在该对象上调用wait 方法的线程,解除其阻塞状态,该方法只能在同步方法或同步块内部调用,如果当前线程不是对象锁的持有者,则抛出IllegalMonitorStatwException异常

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Java ,所有的父都是 java.lang.Object 。 在 Java Object 是所有的根,它是所有祖先,并且是所有的父。所有其他都是从 Object 派生的。 举个例子,如果你定义了一个,例如 MyClass,那么 MyClass 的父就是 Object,并且 MyClass 就是 Object 的子。这意味着 MyClass 继承了 Object 的所有属性和方法。 例如,Object 有一个 toString() 方法,它返回对象的字符串表示形式。如果你定义了一个 MyClass,并且希望使用 toString() 方法来输出 MyClass 的实例,你就可以在 MyClass 重写 toString() 方法,从而使用自定义的表示形式输出 MyClass 的实例。 总之,所有 Java 的父都是 java.lang.Object 。 ### 回答2: 在Java,所有的父ObjectObjectJava所有的根,即所有的终极父。无论是Java的内置还是我们自定义的,它们都直接或间接地继承自ObjectObjectJava的基础库的一部分,它提供了一些通用的方法来处理对象,这些方法包括: 1. equals()方法:用于判断两个对象是否相等。 2. hashCode()方法:用于获取对象的哈希码。 3. toString()方法:用于返回对象的字符串表示。 4. getClass()方法:用于获取对象的运行时。 5. wait()、notify()和notifyAll()方法:用于实现线程之间的等待和通知机制等。 由于所有都继承自Object,因此所有都可以使用这些方法。此外,Object还提供了一些其他的方法,如clone()方法、finalize()方法等。 使用Object作为所有的父,可以使得我们在编写代码时更加方便灵活。例如,当我们需要传递一个对象型的参数时,可以统一使用Object型,以适应各种型的对象。同时,Object还提供了一些通用的方法,能够满足一些基本的需求。当然,如果我们需要更多的功能和特性,可以通过自定义来扩展Object,以满足具体的需求。总而言之,ObjectJava扮演着至关重要的角色,是所有的根基。 ### 回答3: 在Java,所有的父是`Object`。`Object`Java语言的顶级,即所有的终极父。由于所有都直接或间接地继承自`Object`,因此在所有的Java程序,我们都可以调用`Object`定义的共有方法。 `Object`包含了一些常用的方法,包括`equals()`用于比较对象是否相等,`hashCode()`用于获取对象的哈希值,`toString()`用于返回对象的字符串表示等,这些方法在所有都可以直接使用。 由于所有都继承自`Object`,因此我们可以在任何一个的定义使用`super`关键字来引用`Object`的成员或调用`Object`方法。此外,如果我们在自定义的没有显式地声明一个父,那么默认情况下这个都会隐式地继承自`Object`。 总之,在 Java,所有的父都是`Object`,它提供了每个都可以使用的常用方法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值