JDK类库的根类 Object

鳄鱼君

发表文章数:642

热门标签

, ,

Vieu四代商业主题

高扩展、安全、稳定、响应式布局多功能模板。

¥69 现在购买
首页 » Java » JDK类库的根类 Object

任何一个类默认继承Object,就算没有直接继承,最终也会间接继承。Object类中的方法是所有子类通用的。
Object类中常用的方法:

protected Object clone() //负责对象克隆
int hashCode() // 获取对象哈希值
boolean equals(Object obj) // 判断两个对象是否相等
String toString() // 将对象转换成字符串形式
protected void finalize() //垃圾回收器负责调用的方法

API:应用程序编程接口(Application Program Inteerface),整个JDK类库就是一个javase的API,每个API都会配置一个API帮助文档

toString()

将一个“java对象”转换成“字符串表示形式”,建议所有子类都重写该方法

public class Test01 {
    public static void main(String[] args) {
       MyBoBo a1 = new MyBoBo(2020,8,11);
       String s1 = a1.toString();
       System.out.println(s1);// MyBoBo@b4c966a
    }
}

class MyBoBo{
    int year;
    int month;
    int day;

    public MyBoBo() {
    }

    public MyBoBo(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

重写toString方法:

public class Test01 {
    public static void main(String[] args) {
       MyBoBo a1 = new MyBoBo(2020,8,11);
       String s1 = a1.toString();

       // 输入引用的时候,默认调用的是toString()
       System.out.println(s1);// MyBoBo{year=2020, month=8, day=11}
       System.out.println(s1.toString());
    }
}

class MyBoBo{
    int year;
    int month;
    int day;

    public MyBoBo() {
    }

    public MyBoBo(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public String toString() {
        return "MyBoBo{" +
                "year=" + year +
                ", month=" + month +
                ", day=" + day +
                '}';
    }
}

equals()

通过equals方法判断两个对象是否相等

public class Test01 {
    public static void main(String[] args) {
        // 判断两个基本数据类的数据是否相对,直接使用==即可
        // 判断的是a中的100,和b中的100
        int a = 10;
        int b = 10;
        System.out.println(a == b);

        // 判断两个java对象是否相等
        A a1 = new A(2020,8,11);
        A a2 = new A(2020,8,11);
        // 判断的是内存地址
        System.out.println(a1 == a2);
    }
}
class A{
    int year;
    int month;
    int day;

    public A() {
    }

    public A(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

判断两个java对象是否相对,不能使用“==”,因为“==”比较的是两个对象的内存地址,在equals方法的源代码中,也是使用“==”的。现在我们判断的是两个java对象的内容是否相等,所以不够用,需要重写,具体怎么重写,需要根据业务定义:

public class Test01 {
    public static void main(String[] args) {
        // 判断两个java对象是否相等
        A a1 = new A(2020,8,11);
        A a2 = new A(2020,8,11);
        // 判断的是内存地址
        Boolean flog = a1.equals(a2);
        System.out.println(flog);
    }
}
class A{
    int year;
    int month;
    int day;

    public A() {
    }

    public A(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }

    // equals()默认写法
    // public boolean equals(Object obj) {
    //        return (this == obj);
    //    }

    // 重写equals()
    public boolean equals(Object obj){
        int year1 = this.year;
        int month1 = this.month;
        int day1 = this.day;
        if (obj instanceof A){
            A a = (A)obj;
            int year2 = a.year;
            int month2 = a.month;
            int day2 = a.day;
            return year1 == year2 && month1 == month2 && day1 == day2;
        }
        return false;
    }
}

以上代码可以判断两个java对象的内容是否相等,但是效率太低。在IDEA中是可以快速生成equals方法的,以下是IDEA生成的equals方法:

public boolean equals(Object o) {
    // 如果两个对象的内存地址相同,直接返回true
    if (this == o) return true;
    // 如果o是空,直接返回false
    if (o == null) return false;
    // o不是一个A,直接返回false
    if (!(o instanceof A)) return false;
    // if (o == null || !(o instanceof A)) return false;
    A a = (A) o;
    return year == a.year &&
            month == a.month &&
            day == a.day;
}

创建一个字符串对象:

public class Test01 {
    public static void main(String[] args) {
        String a1 = "鳄鱼君";
        String a2 = "鳄鱼君";

        // String也是一个类,属于引用数据类型
        // 那么就可以这样写
        String b1 = new String("鳄鱼君1");
        String b2 = new String("鳄鱼君1");

        // b1和b2保存的内存地址肯定不相同
        System.out.println(b1 == b2);//false
    }
}

所以比较两个字符串不能使用“==”,在String类中,SUN公司重写了equals和toString方法,所以我们可以通过equals方法来比较:

public class Test01 {
    public static void main(String[] args) {
        // String也是一个类,属于引用数据类型
        // 那么就可以这样写
        String b1 = new String("鳄鱼君1");
        String b2 = new String("鳄鱼君1");

        // String类已经重写equlas方法
        System.out.println(b1.equals(b2));//true

        // 也重写toString方法
        System.out.println(b1); // 鳄鱼君1
        System.out.println(b1.toString());// 鳄鱼君1
    }
}

总结:java中基本数据类比较是否相等,使用“==”;java中所有的引用数据类比较统一使用equals!

public class Test01 {
    public static void main(String[] args) {
        Student s1 = new Student(110, "鳄鱼君");
        Student s2 = new Student(110, "鳄鱼君");
        System.out.println(s1.toString());
        System.out.println(s2.equals(s1));
    }
}
class Student{
    // 学号
    int num;
    // 字符串 学校
    String school;

    public Student(){}
    public Student(int num, String school){
        this.num = num;
        this.school = school;
    }

    // 重写toString方法
    public String toString(){
        return "学号:" + num + ",学校:" + school;
    }

    // 重写equals方法,比较学号和学校是否相等
    public boolean equals(Object obj){
        if(this == obj) return true;
        if(obj == null || !(obj instanceof Student)) return false;
        Student s = (Student)obj;
        return this.num == s.num &&
                this.school.equals(s.school);
    }
}

我们在定义类的时候,都需要重写equals方法:

public class Test01 {
    public static void main(String[] args) {
        Address addr1 = new Address("郑州","金水区","23421");
        Address addr2 = new Address("郑州1","金水区","23421");

        User u1 = new User("鳄鱼君",addr1);
        User u2 = new User("鳄鱼君",addr2);
        System.out.println(u1.equals(u2));
    }
}
class User{
   // 用户名
    String user;
    // 住址
    Address addr;

    public User() {}
    public User(String user, Address addr) {
        this.user = user;
        this.addr = addr;
    }
    // 重写equals方法,比较用户名,用户家庭住址相同
    public boolean equals(Object obj){
        if (this == obj)return true;
        if (obj == null || !(obj instanceof User)) return false;
        User u = (User)obj;
        return user.equals(u.user) &&
                addr.equals(u.addr);
    }
}

class Address{
    // 城市
    String city;
    // 街道
    String street;
    // 邮编
    String zipcode;

    public Address() {}
    public Address(String city, String street, String zipcode) {
        this.city = city;
        this.street = street;
        this.zipcode = zipcode;
    }
    // 重写equals方法,比较用户名,用户家庭住址相同
    public boolean equals(Object obj){
        if (this == obj)return true;
        if (obj == null || !(obj instanceof Address)) return false;
        Address a = (Address)obj;
        return city.equals(a.city) &&
                street.equals(a.street) &&
                zipcode.equals(a.zipcode);
    }
}

以上代码还存在问题,会出现空指针异常

finalize()

finalize方法只有一个方法体,里面没有代码,而且这个方法是protected修饰的,这个方法不需要手动调用,JVM的垃圾回收器负责调用这个方法。如果希望在对象销毁时机指向一段代码,这段代码要写到finalize方法中。

java中的垃圾回收器不是轻易启动的,垃圾太少,或者时间没到,种种条件下,有可能启动,也有可能不启动!JDK9以上,该方法已被抛弃!但是可以测试以下:

public class Test01 {
    public static void main(String[] args) {
       for (int i=0;i<1000000;i++){
           // 创建对象
           User u = new User();
           // 把对象变为空
           u = null;
       }
    }
}
class User{
    // 重写finalize方法
    // 对象被垃圾回收器的时候 垃圾回收器负责调用
    protected void finalize() throws Throwable {
        System.out.println("即将被销毁");
    }
}

也可以建议启动GC:

public class Test01 {
    public static void main(String[] args) {
        // 创建对象
        User u = new User();
        // 把对象变为空
        u = null;
        // 建议启动
        System.gc();
    }
}
class User{
    // 重写finalize方法
    // 对象被垃圾回收器的时候 垃圾回收器负责调用
    protected void finalize() throws Throwable {
        System.out.println("即将被销毁");
    }
}

hashCode()

hashCode方法返回的是哈希码,实际上是一个java对象的内存地址,经过哈希算法,得出的一个值,所以hashCode方法的指向结果可以等同看作一个java对象的内存地址:

public class Test01 {
    public static void main(String[] args) {
        // 创建对象
        Object u = new Object();
        int result = u.hashCode();
        System.out.println(result);// 284720968
    }
}
标签:

未经允许不得转载:作者:鳄鱼君, 转载或复制请以 超链接形式 并注明出处 鳄鱼君
原文地址:《JDK类库的根类 Object》 发布于2020-08-11

分享到:
赞(0) 赏杯咖啡

评论 抢沙发

5 + 3 =


文章对你有帮助可赏作者一杯咖啡

支付宝扫一扫打赏

微信扫一扫打赏

Vieu4.6主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。
切换注册

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录
切换登录

注册