Object类和Java中内置的一些接口

一、Object类

Object类是所有类的父类

1.1Object类中的方法

1.1.1toString()方法

Object类中的toString()方法:

public String toString() {
    
    
    return getClass().getName()+"@"+Integer.toHexString(hashCode());
}

要获取自定义类型对象的信息,可以在自定义类型(类)中重写toString方法

System.out.println(person);//在Person类中没有重写toString方法时,打印的是practice.Person@1b6d3586;在Person类中重写toString方法后,打印的是自定义类型对象的信息(但重写的toString方法要写对)

1.1.2equals()方法

比较自定义类型(类)对象中的内容是否相同时,要在自定义类型中重写equals方法,equals方法的返回值是true或fase。建议自定义类型要重写equals方法(使equals方法实现自己想要的比较逻辑)
Object类中的equals方法:

public boolean equals(Object obj) {
    
    
    return (this == obj); // 使用引用直接来进行比较,谁调用equals,谁就是this
}

观察以下代码

Person p1 = new Person("ZhangSan", 20);
Person p2 = new Person("ZhangSan", 20);
int a = 10;
int b = 10;
System.out.println(a == b);//打印true
System.out.println(p1 == p2);//打印false
System.out.println(p1.equals(p2));//打印false

以上代码p1和p2两个人的名字和年龄相同,在这里我们希望System.out.println(p1.equals(p2))打印的是true
在Person类中没有重写equals方法时,下面两行代码没有区别

System.out.println(p1 == p2);
System.out.println(p1.equals(p2));

所以要在Person类中重写Object类中的equals方法,可以手动重写,也可以用idea生成,点击Generate和equals() and hashCode()

 @Override
    public boolean equals(Object obj) {
    
    
        if(obj == null) {
    
    //p1可以调用equals方法,说明p1指向的人已经创建好,p2为null不指向任何对象,说明p2指向的人没有被创建好
            return false ;
        }
        if(this == obj) {
    
    
            return true ;
        }
        if(!(obj instanceof Person)) {
    
    //检查obj是否引用了Person类型的对象
            return false ;
        }
        Person person = (Person)obj ;//向下转型,因为obj是父类引用
        return this.name.equals(person.name) && this.age==person.age ;
    }

1.1.3hashCode()方法

建议自定义类型要重写hashcode方法,可以简单地认为hashcode方法返回的是对象的地址,但这个地址是被处理过的
hashcode方法源码:

public native int hashCode();

hashcode方法由native修饰,底层是由C/C++代码写的,我们看不到

Person per1 = new Person("yixing", 20) ;
Person per2 = new Person("yixing", 20) ;
System.out.println(per1.hashCode());//打印460141958
System.out.println(per2.hashCode());//打印1163157884

以上代码p1和p2两个人的名字和年龄相同,在这里我们希望System.out.println(per1.hashCode())和System.out.println(per2.hashCode())打印的结果一样,所以要在Person类中重写Object类中的hashCode方法
下面是用idea生成重写的hashCode方法:

@Override
public int hashCode() {
    
    
return Objects.hash(name, age);
}

在Person类中重写Object类中的hashCode方法后,将p1和p2两个人的name和age传入重写的hashCode方法里的Objects.hash(name, age),Objects.hash(name, age)在逻辑上帮我们算出了这是同一个位置,返回这同一个人的地址

二、Java中内置的一些接口

2.1Comparable接口

(1)自定义类型的对象要比较大小,则在这个自定义类型(类)中实现Comparable接口,在这个自定义类型(类)中重写compareTo方法,来实现比较的逻辑,因为Comparable接口中的compareTo方法没有具体的实现,compareTo方法的返回值是int,Comparable的T是什么类型(如Person类型),compareTo的参数就是什么类型(如Person类型),因为Comparable源码的泛型是这样写的

class Person implements Comparable<Person>{
    
    
    public String name ;
    public int age ;
    public Person(String name, int age) {
    
    
        this.age = age ;
        this.name = name ;
    }
    @Override
    public int compareTo(Person o) {
    
    //重写compareTo方法后,compareTo用人的年龄来进行比较
        return this.age - o.age;
    }
}
public class Practice1 {
    
    
    public static void main(String[] args) {
    
    
        Person p1 = new Person("ZhangSan", 15) ;
        Person p2 = new Person("LiSi", 20) ;
        System.out.println(p1.compareTo(p2));//输出结果是-5
    }
}

数组排序Arrays.sort(arrays)底层是将数组的内容拿出来,强制类型转换为Comparable类型再调用compareTo方法(((Comparable)a[runHi++]).compareTo(a[lo])),数组内容是整数时可以用sort直接比较,数组内容是对象的引用时,则要在数组内容的类型(类)中实现comparable接口和重写compareTo方法
comparable接口对类的侵入性比较强,较不灵活
(2)使用比较器,对类的侵入性不强,较灵活,比较器(重新定义一个类,在这个类实现Comparator接口,在这个重新定义的类中重写compare方法,要比较时new一个这个重新定义的类的对象,用这个对象调用重写的compare方法),Comparator的T是什么类型(如Student类型),compare的参数就是什么类型(如Student类型),因为Comparator源码的泛型是这样写的

class AgeComparator implements Comparator<Student>{
    
    
    @Override
    public int compare(Student o1,Student o2){
    
    
        return o1.age-o2.age;
    }
}
class NameComparator implements Comparator<Student> {
    
    
    @Override
    public int compare(Student o1,Student o2){
    
    
        return o1.name.compareTo(o2.name);
    }//o1.name是String类型的引用,String类中实现了Comparable接口和重写了compareTo方法
}

public class Test{
    
    
    public static void main(String[] args) {
    
    
        Person p1 = new Person("ZhangSan", 10);
        Person p2 = new Person("LiSi", 15);
        AgeComparator ageComparator = new AgeComparator();
        System.out.println(ageComparator.compare(p1, p2));
        NameComparator nameComparator = new NameComparator();
        System.out.println(ageComparator.compare(p1, p2));
    }
}

2.2Cloneable接口

(1)Object类中有clone方法
以下是浅拷贝:

class Person implements Cloneable{
    
    //克隆接口Cloneable(空接口/标记接口),证明当前类是可以被克隆的
    public int age;
    public Person(int age){
    
    
        this.age = age;
    }
    @Override
    protected Object clone() throws CloneNotSupportedException{
    
    //这里重写了Object类的clone方法,Object类的clone方法声明的异常是受查异常/编译时异常,必须是编译时处理
        return super.clone();//clone()在Object类中是protected修饰的(不是public修饰),所以要在Test2类中用person1调用clone()来克隆person1指向的对象,则要在Person类中重写clone()方法,这个重写的clone()方法里面用super调用Object类的clone()方法
    }
}
public class Test2{
    
    
    public static void main (String[] args) throws CloneNotSupportedException{
    
    //声明clone方法会出现的异常
        Person person1 = new Person(10);
        Person person2 = (Person)person1.clone();//向下转型,要强制类型转换,因为clone()方法的返回值类型是Object类型,返回值类型是父类。这里person1调用克隆方法,克隆person1指向的对象
        System.out.println(person1);//以下两个打印的结果相同
        System.out.println(person2);
    }
}

(2)浅拷贝:只克隆对象。深拷贝:克隆对象中的对象。
以下是深拷贝:

class Money implements Cloneable{
    
    
    public double money = 10.0;
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        return super.clone();
    }
    @Override
    public String toString() {
    
    
        return "Money{"+"money="+money+'}';
    }
}
class Person implements Cloneable{
    
    
    public int age;
    public Money m;//这里用了组合
    public Person(int age){
    
    
        this.age = age;
        this.m = new Money();
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
    
    
        Person tmp = (Person) super.clone();
        tmp.m = (Money) this.m.clone();//clone()在Money类中虽然是protected修饰,但这里是同一个包下的不同类,所以可以在Person类中通过对象的引用调用Money类的clone()以克隆Money类对象
        return tmp;                    //克隆this.m所指向的内容,谁调用这个方法谁就是this,p1调用了这个方法所以p1是this,克隆p1.m所指向的内容
    }
    @Override
    public String toString() {
    
    
        return "Person{"+"age="+age+",m="+m+'}';
    }
}
class Test2 {
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        Person p1 = new Person(10);
        Person p2 = (Person) p1.clone();
        System.out.println(p1);
        System.out.println(p2);
        p2.m.money = 20.0;
        System.out.println(p2);
    }
}

在这里插入图片描述
打印结果是:
在这里插入图片描述
p2.m.money = 20.0改变了p2对象中的m对象里money的内容,说明p2对象中的m对象也被克隆出来了。

猜你喜欢

转载自blog.csdn.net/zhanlongsiqu/article/details/131056622