Java的Object基类公共方法

目录

1、clone()方法

2、equals()和hashCode()方法

3、finalize()方法

4、getClass()

5、notify、notifiAll和wait()

6、toString()方法


object类除了object()构造方法外,还提供了11个成员方法

根据jdk-1.8API中可见

 也就是如下表格所示:

object基类方法
Modifier and typemethoddescription
protected Objectclone()创建并返回该对象的副本
booleanequals(Object obj )指示一些其他对象是否等于此
protected voidfinalize()当垃圾收集确定不再有对该对象的引用时,垃圾收集器在对象上调用
类<?>getClass()返回此Object的运行时类
inthashCode()返回对象的哈希码值
voidnotify()唤醒正在等待对象监视器的单个线程
voidnotifyAll()唤醒正在等待对象监视器的所有线程
StringtoString()返回对象的字符串表示形式
voidwait()导致当前线程等待,直到另一个线程调用该对象的notify()或notifyAll()方法
voidwait(long timeout)导致当前线程等待,直到另一个线程调用该对象的notify()或notifyAll()方法,或指定时间已过
voidwait(long timeout,int nanos)导致当前线程等待,直到另一个线程调用该对象的notify()或notifyAll()方法,或者某些其他线程中断当前线程,或一定量的实习时间

1、clone()方法

这个方法是为object克隆对象而生的,它不是简单的copy ,也不是简单的new 一个对象,clone()方法存在的意义在于Java语言的对象引用机制

如:

Person p1 = new Person();
Person p2 = p1;

此时,p1和p2引用的是同一个对象,这个对象在jvm的堆内存中是共享的,也就是说如果P2改变,那么p1也会随之改变。

那么要避免p1随着p2改变,应该怎么做?

------使用clone()方法。这个方法可以在堆中克隆出另外一个对象,这样p1不会随着p2改变,因为他们引用的不再是同一个对象。

注意:首先要实现Cloneable接口,然后在类中重写Object类中的clone方法

代码示例如下:

public class CloneTest implements Cloneable {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name="mq";
        p1.age=22;
        Person p2 = p1;
        p2.name="mq2";
        System.out.println("p1=="+p1.toString());
        System.out.println("p2=="+p2.toString());
    }
}
//输出结果p1==Person{name='mq2', age=22}--p2==Person{name='mq2', age=22}
//在Person中重写clone()方法
class Person implements Cloneable {
    String name;
    int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    @Override
    protected Object clone() throws CloneNotSupportedException {
        // TODO Auto-generated method stub
        Person p=null;
        p=(Person) super.clone();
        return p;
    }
    //修改测试类代码
 Person p2 = null;
        try {
            p2 = (Person) p1.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        p2.name="mq2";
//输出结果:p1==Person{name='mq', age=22}--p2==Person{name='mq2', age=22}

2、equals()和hashCode()方法

在Java中,有时候判断两个对象之间的相等关系,并不能仅仅通过“=”或“==”来进行判定。

“==”只是比较两个对象的地址是否一致,当然如果返回为true,那当然相等,地址相同肯定是同一对象。

但大部分时候,我们比较俩对象时,并不是将引用同一对象的引用来进行比较的。如,随便new两个对象进行比较,新new的两个对象地址肯定不同,这时候“==”返回的就是false。

那是否说明两个对象不同呢?

并不能说明,程序里面的对象是否相等,并不是但从地址是否一致来考量的,还要从程序员的比较和考量的角度(判断相等的标准由程序员决定)

这时候就要重写equals()、hashCode()方法了

hashcode()方法其实就是对应对象的地址,调用它的时候,它的返回值就是对象的地址(在hash表中对应的位置)。

equal()方法则是比较两个对象的具体方法描述,或者说规则。也就是说,你要比较两个对象是否相等。你的比较原则是什么,怎么去比较,就重写在equal()方法中。

equals()方法和hashcode的关系:

  1. 如果两个对象equals相等,那么这两个对象的HashCode一定也相同

  2. 如果两个对象的HashCode相同,不代表两个对象就相同,只能说明这两个对象在散列存储结构中,存放于同一个位置

为什么重写equals()方法后,还建议重写hashCode()方法?

  • 使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率

  • 保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了避免这种情况的出现。

 代码示例:

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Student student = (Student) o;
        return sno.equals(student.sno) && name.equals(student.name);
    }

    @Override
    public int hashCode() {
        int hash=name.hashCode()+sno.hashCode()+1;
        return hash;
    }

3、finalize()方法

finalize()方法是专供垃圾回收提供的,在GC回收某个对象的时候,首先会调用该对象的finalize()方法。

当一个堆空间中的对象没有被栈空间变量指向的时候,这个对象会等待被JVM回收

只是告诉java这个调用对象可以回收,但不能强制启动GC进行回收,jvm会在合适的时候进行回收(内存不足时)

protected void finalize() throws Throwable{
}
//jdk9以后过时

4、getClass()

此方法与反射有关。用于返回一个返回该对象的运行时类的java.lang.Class对象。也就是运行中的对象本身。

       Student stu1 = new Student();
        Class stuClass = stu1.getClass();
        System.out.println(stuClass.getName());

5、notify、notifiAll和wait()

这三个方法是用来实现多线程的。

wait():来阻塞线程,wait()被调用后,线程将会进行等待状态,锁被释放,同时线程也会让出cpu资源,其他的线程可以运行。

notify()\notifyAll():方法用于唤醒线程,调用notify\notifyAll方法后,不会立即释放锁,而是等待sychronize代码块执行完后。或者遇到wait()方法后,在释放锁。

因此,有一点要非常注意,notify、notifiAll和wait()是必须在sychronize包含的代码快中使用。这跟thread类的sleep方法是不一致的,sleep()方法可以在任意地方使用。

6、toString()方法

返回对象的字符串表现形式

若没有覆盖toString(),在使用对象直接输出的时候,默认输出的是一个对象在堆内存上的地址值。

public class toStringTest {
    public static void main(String[] args) {
        People p1 = new People("MQ",18);
        System.out.println("未覆盖toString()输出:"+p1);
    }
}
class People{
    private String name;
    private int age;

    public People(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
>>>输出:未覆盖toString()输出:test.People@4554617c
    
//覆盖toString()后
    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
>>>输出:覆盖toString()输出:People{name='MQ', age=18}

 提问:为什么字符串可以通过+进行不同类型数据拼接?

System.out.println("mq"+666);
>>>输出:mq666

Object是所有类的父类,任意类都是继承Object类的。而Object中定义了 toString()方法,所以任意类中都包含了toString()方法,对象在实例化之后都可以调用。

String作为信息输出的重要数据类型,在Java中所有的数据类型只要遇见String就执行了+,都要求其变为字符串后连接,而所有对象想要变为字符串就默认用toString( )方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaomaO。O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值