Object类
1,Object类存在于Java.lang包中,编译时会自动导入,他是所有类的根类。Java中的每个类都直接或间接使用Object类作为父类,所有对象都实现这个类的方法。
2,所有类对Object类的继承是Java默认的,无需使用extends明确表示。即使是程序中自定义的一个类,实际上也不是独立的,Java已经把它定义为Object类的子类
3、Object 类可以显式继承,也可以隐式继承,以下两种方式是一样的:
显式继承:
public class Runoob extends Object{
}
隐式继承:
public class Runoob {
}
Object类中常用的方法:
equals():
1,equals()方法的源代码:
public boolean equals(Object obj){
return (this==obj)
}
可以看出就是在比较引用是否相同,所以这个方法是不够用的,一般会被重写,用来比较对象是否是同一个。
注意:String类和包装类都已经重写了equals()方法,可以直接比较对象内容是否相同。
但是要注意,String对象内容如果相同,在不使new关键字创建对象时用==比较引用也是比较的对象内容。
跟String对象存储方式有关。它是存储在常量池当中。
2,代码演示:
没有重写equals()的情况:
public class ObjectTest01 {
public static void main(String[] args) {
//包装类对象
Integer i= new Integer(10);
Integer i1= new Integer(10);
System.out.print(i==i1);
System.out.print(" ");
System.out.println(i.equals(i1));
//字符串对象
String s="张三";
String s1="张三";
System.out.print(s==s1);
System.out.print(" ");
System.out.println(s.equals(s1));
//自定义类,没有重写equals方法
Student stu = new Student("张三");
Student stu1 = new Student("张三");
System.out.print(stu==stu1);
System.out.print(" ");
System.out.print(stu.equals(stu1));
}
}
class Student{
private String name;
public Student(String name) {
this.name = name;
}
}
结果:
false true
true true
false false
重写equals()方法的情况:
注意:equals方法重写,怎么比较是程序员自己定的
但是一般用idea工具生成的,不满足自己需求可以改
public class ObjectTest01 {
public static void main(String[] args) {
//自定义类,重写equals方法
Student stu = new Student("张三");
Student stu1 = new Student("张三");
System.out.print(stu==stu1);
System.out.print(" ");
System.out.print(stu.equals(stu1));
}
}
class Student{
private String name;
public Student(String name) {
this.name = name;
}
//注意 equals方法重写,怎么比较是程序员自己定的
//但是一般用idea工具生成的,不满足自己需求可以改
@Override
public boolean equals(Object o) {
//如果引用都相等直接返回true
if (this == o) return true;
//如果传过来的对象都不是同一个类型直接返回false
if (!(o instanceof Student)) return false;
//比较两个对象的名字是否相同,相同返回true,不同返回false
return this.name==((Student) o).name;
}
}
结果:
false true
toString():
1,在Object类中的源码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
可以看出,使用源代码的toString方法返回的是:
类名@对象的内存地址转换为十六进制----的形式
设计toString方法的目的:
通过调用这个方法可以将一个“Java”对象转换成“字符串”,方便程序员直观的看
几乎所有类都重写了这个方法,自定义的类得自己重写
2,toString方法是怎么使用的。
当你使用"System.out.println(address)"语句时,其实会自动在address后面添加一个".toString()"。一般情况下我们是省略的。
而如果你不重写这个方法就会去父类找这个方法。(如果没有会找到顶级父类Object)
其中"city"是Address类定义的一个属性,其对象为String,就会调用String类里面的toString()方法
代码示例:
public class ObjectTest02 {
public static void main(String[] args) {
Man man = new Man("张三");
Woman woman = new Woman("小红");
//两个都是调用的是本类的toString方法
System.out.print(man+" ");//只是省略没写
System.out.print(man.toString()+" ");
//两个都是调用的是String类的toString方法
System.out.print(man.name+" ");//只是省略没写
System.out.println(man.name.toString());
System.out.println("==========");
//两个都是调用的是Object中的toString()方法
System.out.print(woman+" ");//只是省略没写
System.out.print(woman.toString()+" ");
//两个都是调用的是String类的toString方法
System.out.print(woman.name+" ");//只是省略没写
System.out.println(woman.name.toString());
}
}
class Man{
String name;
public Man(String name) {
this.name = name;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
'}';
}
}
class Woman{
String name;
public Woman(String name) {
this.name = name;
}
}
结果:
Man{name='张三'} Man{name='张三'} 张三 张三
==========
task08.Woman@1540e19d task08.Woman@1540e19d 小红 小红
hashCode方法:
1, hashCode方法在Object类中源码:
public native int hashCode();
注意:这个方法不是抽象方法,带有native关键字,底层调用C++程序。
hashCode()方法返回的是哈希码值:
实际上就是一个Java对象的内存地址,经过哈希算法,得出的一个值。
所以hashCode()方法的执行结果可以等同看作一个Java对象的内存地址。
2,代码演示:
public class ObjectTest03 {
public static void main(String[] args) {
A a = new A();
int i = a.hashCode();
Object o = new Object();
int i1 = o.hashCode();
System.out.println("对象A的哈希值:"+i);
System.out.println("对象Object的哈希值:"+i1);
}
}
class A{
}
结果:
对象A的哈希值:356573597
对象Object的哈希值:1735600054
finalize():
1,finalize()方法在Object中的源码:
protected void finalize() throws Throwable { }
注意:
1,finalize()方法只有一个方法体,里面没有代码
2,这个方法不需要程序员手动调用,JVM的垃圾回收器负责调用这个方法。
3, finalize()方法的执行时机:
当一个Java对象即将被垃圾回收器回收时,垃圾回收器负责调用finalize()方法
4, finalize()方法实际上时SUN公司为Java程序员准备的一个时机,垃圾销毁时机。
如果希望在对象销毁时机执行这一段代码的话这段代码需要写到 finalize()方法体中。
在代码示例之前的了解:
java中的并非总是被垃圾回收,也就是说对象可能不被回收。一般程序只要不到濒临存储空间用光,垃圾回收器一般都不会主动回收内存,如果程序结束,并且垃圾回收器一直没有释放你创建的空间,则随着程序的退出,资源则会被归还给操作系统。所以上面的我们finalize()才一直没有被调用
System.gc();会强制系统垃圾回收器工作
Java语言规范并不保证finalize方法会被及时地执行、而且根本不会保证它们会被执行
2, 代码示例:
public class ObjectTest04 {
public static void main(String[] args) {
for (int i=0;i<8;i++){
new B();
System.gc();
}
}
}
class B{
public B() {
}
@Override
protected void finalize() throws Throwable {
System.out.println("对象马上要被销毁了");
}
}
结果:(就执行了一次)
对象马上要被销毁了