java.lang.Object是JAVA中所有类层次结构的根,所有的对象包括数组都实现了Object类的方法。
构造器:
public Object()
方法:
1. clone()
该方法需要实现Cloneable接口,重写clone方法才能使用;
该方法会返回一个一摸一样的对象,但是该对象不等同于原来的对象
x.clone() != x;
例如:
class Person implements Cloneable{
public String name;
public int age;
public Person(String name,int age ) {
this.age = age;
}
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("小明",18);
Person p2 = p1.clone();
Person p3 = p1;
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1==p3);
}
}
输出:
//后面的只是人为加的注解
366712642 //p1的hashCode
1829164700 //p2的hashCode
false //p1==p2
true //p1==p3
该方法是完全克隆了一个对象,并不仅仅是创建一个引用指向原来的对象。
但是需要注意,如果一个对象里面的属性包含引用的话,那么该引用属性也要实现Cloneable接口,因为引用在内存中存储的只是引用对象的hash值,克隆也只是克隆了hash值而已。
例如:
class Body{
public int BODYNUM = 4;
}
class Person implements Cloneable{
public String name;
public int age;
public Body body; //body属性
public Person(String name,int age,Body body ) {
this.name = name;
this.age = age;
this.body = body;
}
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("小明",18,new Body());
Person p2 = p1.clone();
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1.body==p2.body);
p1.body.BODYNUM = 5;
System.out.println(p2.body.BODYNUM);
}
}
输出:
366712642
1829164700
false //p1==p2
true //p1.body==p2.body
5 //p2的body属性的一个值
可以看到,修改了p1的body属性,p2的 body属性也修改了。那么就说明了,其实p1的body跟p2的body实质上还是同一个,因为克隆的只是引用值而已,引用还是指向内存中同一个区域。
这个时候,Body属性必须也实现Cloneable接口
例如:
class Body implements Cloneable{
public int BODYNUM = 4;
public Body clone() throws CloneNotSupportedException {
return (Body) super.clone();
}
}
class Person implements Cloneable{
public String name;
public int age;
public Body body;
public Person(String name,int age,Body body ) {
this.name = name;
this.age = age;
this.body = body;
}
public Person clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.body = body.clone(); //可以认为将包含引用的属性都要自己拷贝一遍
return person;
}
}
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person("小明",18,new Body());
Person p2 = p1.clone();
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p1==p2);
System.out.println(p1.body==p2.body);
p1.body.BODYNUM = 5;
System.out.println(p2.body.BODYNUM);
}
}
输出:
366712642
1829164700
false
false //p1的body与p2的body不一样了
4 //修改p1的body后,p2并未受到修改
这也就是传说中的深拷贝,即在重写clone方法中拷贝所有的引用属性;
2. equals(Object obj)
该方法具有如下特性:
- 自反性:对于任何非空引用x; x.equals(x)应当返回true;
- 对称性:对于任何非空引用x,y;x.equals(y)返回true当且仅当y.equals(x)返回true;
- 传递性:对于任何非空引用 x,y,z,如果x.equals(y)=true,y.equals.(z)=true,那么x.equals(z)=true
- 一致性:对于任何非空引用 x,y,调用多次x.equals(y)返回结果应该相同;
- 对于任何非空引用x,xequals(null)应该返回false;
源码如下:
public boolean equals(Object obj) {
return (this == obj);
}
很多都会重写该方法。
3. finalize()
是终止函数,JVM在进行垃圾回收的时候首先会调用这个函数,当某个对象被确认为无用信息的时候,那么就会释放该对象的内存,但是不一定有效。
一般人为不使用该方法。
class Person{
//重写了Object类的finalize方法,当Person类被回收的时候首先调用该方法
public void finalize() throws Throwable{
System.out.println("回收前调用");
}
}
public class Run {
public static void main(String[] args) {
Person p = new Person();
p = null;
System.gc();
}
}
输出:
回收前调用
表明gc的时候调用了Person类的finalize方法
但是需要注意,只有p没有指向的时候,即被认为是无用信息的时候才会被回收,如果去掉上面的p=null,那么还是不会有输出。
4. getClass()
返回该对象运行时的类。
例如:
public class Run{
public static void main(String[] args) throws CloneNotSupportedException {
String a = "a";
System.out.println(a.getClass());
}
}
输出:
class java.lang.String
5. hashCode()
该方法返回对象的hash值,具有如下特点:
- 同一对象调用多次该方法应该返回相同值
- 如果两个对象通过equals方法返回true,那么调用hashCode方法应该返回相同hash值
- 不是一定要“两个对象通过equals方法返回true,那么调用hashCode方法应该返回相同hash值”,但是通常应该这么做,提高HashTable的性能
6. notify()
该方法唤醒在此同步监视器上等待的一个线程,如果有多个线程等待,则随机唤醒一个。
- 如果在synchronized修饰的同步方法中使用,则可以直接使用该方法,因为this就是同步监视器
- 如果在synchronized修饰的同步代码块中使用,则使用括号中的同步监视器来调用该方法。
7. notifyAll()
该方法唤醒在此同步监视器上等待的所有的线程。
8. toString()
该方法将任何对象转换为字符串类型
返回getClass().getName() + '@' + Integer.toHexString(hashCode())
例如:
public class Run {
public static void main(String[] args) {
Run r = new Run();
System.out.println(r.toString());
System.out.println(r.toString() instanceof String);
}
}
输出:
hello.Run@15db9742
true
9. wait()
该方法将当天线程进入等待,直到有其他线程唤醒它。