Object类
Object是所有类的顶级超类,其中有两个经常被子类重写的方法:
toString()与equals().
Object类是java.lang包下的核心类,Object类是所有类的父类,何一个类时候如果没有明确的继承一个父类的话,那么它就是Object的子类;
class Person { }
class Person extends Object { }
以上两种的定义最终效果都是一样的。
Object类的结构图(Object提供了11个方法)
下面我们一个个方法进行分析,看这些方法到底有什么作用:
1. clone()
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2. getClass()
final方法,返回Class类型的对象,反射来获取对象。
3. toString()
该方法用得比较多,一般子类都有覆盖,来获取对象的信息。
4. finalize()
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5. equals()
比较对象的内容是否相等
6. hashCode()
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
7. wait()
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
其他线程调用了该对象的notify方法。
其他线程调用了该对象的notifyAll方法。
其他线程调用了interrupt中断该线程。
时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
8. notify()
该方法唤醒在该对象上等待的某个线程。
9. notifyAll()
该方法唤醒在该对象上等待的所有线程。
public class ObjectDemo {
public static void main(String[] args) {
//可以是使用Object接收所有类的对象
//Object类是属于java.lang包,该包下所有的类
//都不需要手动导入,系统会在编译期间自动导入
//Object per = new Person();
Object stu = new Student();
Object object = new Object();
}
}
Object常用方法 :
toString():取的对象信息
equals():对象内容比较
toString()方法
//toString()取得对象信息,返回该对象的字符串表示
Student stu2 = new Student();
System.out.println(stu2);
/**
* 在使用对象直接输出是,默认输出的是一个对象在堆内存中的
* 内存地址,如果需要输出对象信息,则要重写toString方法
*/
Person person = new Person("张三", 18);
System.out.println(person);
toString的核心目的在于取得对象信息,它作为重要的数据类型,在java所有的数据类型遇见String就执行了“+” 字符串拼接。
System.out.println("hello"+123);//hello123
对于上述例子,就是由于String的父类是Object,父类中定义toString()方法,所以任意中都包含toString()方法
对象在实例化后就可以调用toString()方法。
每一个类中都包含toString()方法 但并不是每一个类都重写Object类toString()方法
在Object类的源码中,可以发现通过反射,获取到了当前对象的全类限定名(包名+类名)和@十六进制哈希值字符串。这就是不重写toString()是直接打印输出的内容.
equals方法
equals():对象比较
String类对象比较 使用的是 equals()方法,实际上String类的equals()方法就是覆写 Object类中的equals()方法
-
基本数据类型的比较用 == (如: a == 3,b == 4, a == b,比较的是值是否相等)
-
引用类型数据比较:调用 equals()方法进行比较
用equals( )来比较对象内容是否相同:
equals()方法:对象比较
String类对象比较使用的equals()方法,实际上
String类的equals()方法就是重写Object类中的
equals()方法。
基本数据类型比较用的是 ==(比如:a==3 b==4 a==b是比较
数值是否相等。)
引用数据类型之间比较:调用equals()方法进行比较
Person p1 = new Person("张三", 18);
Person p2 = new Person("张三", 18);
System.out.println(p1.equals(p2));//false
}
}
上述两个内容相同的对象,去做equals()比较为什么结果
会是false?
因为此时直接调用equals()方法默认进行比较的是两个对象的
地址。
在Object类的源代码中当前对象与传递过来的对象比较还是
地址值(==) 返回boolean值
如果要在判断一个类的两个对象姓名的内容是否相同时
我们需要重写equals()方法
class Person{
//属性
private String name;
private int age;
//有参构造方法
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//如果想要用toString方法去输出对象的信息,就必须
//在类中重写Object类中toString()方法
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
对于上述一个类的两个对象内容比较,如果不去在类中重写、
Object的equals()方法则比较的是两个类对象的地址是否相同。
那么,如果想要比较两个类对象的内容是否相同则需要在类
中重写equals()方法。此时会提供多种比较选择。
@Override
public boolean equals(Object obj) {
//1.判断当前的两个类对象地址是否相同
if (this == obj)
return true;
//2.传递进来的对象是否为空
if (obj == null)
return false;
//3.判断两个对象是否为同一类
if (getClass() != obj.getClass())
return false;
//向下造型
Person other = (Person) obj;
//4.判断两个对象的内容是否相同
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
class Student{}
所以经过上述例子,我们可以观察出,引用类型的数据在进行比较时,应该先重写equals()方法,不然比较的还是两个对象的堆内存地址值,必然不会相等。