Java Object详解

我们都知道:在Java中,所有的类都继承了Object这个基类,并且大家都知道,Object有几个比较通用的方法,如equals(),clone(),toString(),我们需要在使用它们的时候进行覆写,今天,我们就具体的探究下这几个方法。

void registerNatives()

这是个Native方法,在静态块中调用,其目的是将hashCode,wait,notify,notifyAll和clone方法注册到本地。

Class<?> getClass()

同样是个Native方法,获取对象的Class。

int hashCode()

Native方法,生成哈希码,其中注意三点

  • 一个对象在同一个进程被多次调用,但是它的哈希码仍然应该是相同的。但是,当同一个对象在不同进程中执行,则哈希码有可能不同。JavaDoc原文如下

    Whenever it is invoked on the same object more than once during an execution of a Java application, the {@code hashCode} method must consistently return the same integer, provided no information used in {@code equals} comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

  • 如果两个对象通过equals()比较返回true,那么它们的哈希码应该相同。
  • 如果两个对象通过equals()比较返回false,那么它们的哈希码应该不同。

boolean equals(Object obj)

这恐怕使我们最常用的方法之一了,我们在实际应用中,也经常遇到什么时候用equals(),什么时候用==的问题。一般来说,基本数据类型用==,因为这样可以直接比较它们的值,但是复合数据类型如果我们用==的话,那么实际上我们比较的就是它们的引用了,除非它们指向的是同一个对象,否则它们不可能相等,因此我们比较符合数据类型一般用equals(),并且我们应该覆写equals(),这是因为Object的equals()方法默认的也是用==进行判定:

public boolean equals(Object obj) {
        return (this == obj);
    }

我们再来看看我们经常用的String是如何覆写equals()方法的:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

在这里还有一个很有趣的问题,请看下面的例子

    String s1 = "String";
    String s2 = "String";

    System.out.println("The result is " + s1.equals(s2));

你会发现返回值为True,这个就和我们上面讲的不一样了,按照我们上面的讲解,这时候应该返回false才对。其实是这样的,因为JVM中会维护一个字符串池,如果池中已经有包含此对象的字符串的时候,那么它就会返回池中的字符串(当然如果你new一个新的String对象的话就另当别论。)所以这个时候返回的是true。

Object clone()

Native方法,我们一般用它来复制一个对象,并且用clone()可以实现深复制(将所有需要复制的对象都复制了一遍,而不单单是用引用指向原来的对象。)示例如下:

public class Animal implements Cloneable {
    private int height;
    private int age;

    public Animal(int height, int age){
        this.height = height;
        this.age = age;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public String toString() {
        return "Animal{" +
                "height=" + height +
                ", age=" + age +
                ‘}‘;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

public class People implements Cloneable {

    private int height;
    private int age;
    private Animal a;

    public People(int height, int age,Animal a){
        this.height = height;
        this.age = age;
        this.a = a;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        People p = (People) super.clone();
        p.a = (Animal) a.clone();
        return p;
    }

    @Override
    public String toString() {
        return "People{" +
                "height=" + height +
                ", age=" + age +
                ", a=" + a +
                ‘}‘;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setAnimalAge(int a) {
        this.a.setAge(5);
    }
}

接下来我们这样调用:

    Animal a1 = new Animal(100,3);
    People p1 = new People(173,24,a1);

    People p2 = (People) p1.clone();
    p2.setAge(26);
    p2.setHeight(181);
    p2.setAnimalAge(6);

    System.out.println(p1.toString());
    System.out.println(p2.toString());

这样我们就完成深复制了。

String toString()

最常用的方法,我们一般用它获取对象成员变量的值。Object的默认实现:

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

void notify(),void notifyAll()

Native方法,多线程时应用,通知其他线程等待结束。

void wait(long),void wait(long,int),void wait()

Native方法,通知线程等待。

void finalize()

垃圾回收。当JVM判断一个对象可以被垃圾回收时,那么JVM会调用finalize()方法,但是记住,它只能调用一次(所以如果你想这个对象不被垃圾清除的话,你就要在这里面做点事情了),但是一般你不能依赖在这里做垃圾回收的工作,在《Java编程思想》中说明了有关finalize()的一个用法,那就是通过finalize()来进行对象终结对象的判断。

时间: 2024-09-28 21:32:24

Java Object详解的相关文章

Java记录 -22- Java的基类Object详解

Java的基类Object详解 Java的JDK文档要经常查阅使用,最好查看英文的文档. java.lang.Object 类,java.lang包在使用的时候无需显示导入,编译时由编译器自动帮助我们导入. API(Application Programinga Interface),应用编程接口. Object obj = new Object(); System.out.println(obj); System.out.println(obj.toString()); 上面打印的两个内容一样

java 反射 详解

本文来自:blog.csdn.net/ljphhj JAVA反射机制:   通俗地说,反射机制就是可以把一个类,类的成员(函数,属性),当成一个对象来操作,希望读者能理解,也就是说,类,类的成员,我们在运行的时候还可以动态地去操作他们. 理论的东东太多也没用,下面我们看看实践 Demo - Demo: package cn.lee.demo; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import

Java synchronized详解

Java synchronized详解 第一篇: 使用synchronized 在编写一个类时,如果该类中的代码可能运行于多线程环境下,那么就要考虑同步的问题.在Java中内置了语言级的同步原语--synchronized,这也大大简化了Java中多线程同步的使用.我们首先编写一个非常简单的多线程的程序,是模拟银行中的多个线程同时对同一个储蓄账户进行存款.取款操作的. 在程序中我们使用了一个简化版本的Account类,代表了一个银行账户的信息.在主程序中我们首先生成了1000个线程,然后启动它们

Java虚拟机详解——JVM常见问题总结

[正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考之前的系列文章,尤其是那篇:Java虚拟机详解04--GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾回收.类加载机制. 先把本文的目录画一个思维导图:(图的源文件在本文末尾) 一.Java引用的四种状态: 强引用:  用的最广.我们平时写代码时,new一个Object存放在堆内存,然后用一个引用指向它,这就是强引用. * 如果一个对象具有强引用,那垃圾回收器绝不会回收它*.当内存空间不足,Java虚拟机宁

Java引用类型详解

JVM  的垃圾回收器对于不同类型的引用有不同的处理方式.java中对于一个对象来说,只要有引用的存在,它就会一直存在于内存中.如果这样的对象越来越多,超出了JVM中的内存总数,JVM就会抛出OutOfMemory错误.虽然垃圾回收的具体运行是由JVM来控制的,但是开发人员仍然可以在一定程度上与垃圾回收器进行交互,其目的在于更好的帮助垃圾回收器管理好应用的内存.这种交互方式就是使用JDK1.2 引入的  java.lang.ref包. 强引用(strong reference) 在一般的 Jav

Java面向对象详解

Java面向对象详解 前言:接触项目开发也有很长一段时间了,最近开始萌发出想回过头来写写以前学 过的基础知识的想法.一是原来刚开始学习接触编程,一个人跌跌撞撞摸索着往前走,初学的时候很多东西理解的也懵懵懂懂,后来实践的多了,有些东西才慢慢清 楚:二是经过一定的实践之后,反过头来再去学习一些基础东西才能够理解的更透彻:三是有些东西基础但是确很重要,是值得好好搞一搞的. 1.面向对象 面向对象(Object Oriented)是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),

Java反射详解

Java反射详解 分类:java, 基础日期:2012-07-20作者:ticmy 19 反射,是Java中非常重要的一个功能,如果没有反射,可以说很多框架都难以实现. 什么是反射?说白了就是可以通过Java代码获取装载到方法区的类信息的手段. 当装载一个类时,会在方法区产生一个数据结构,该结构中包含着装载的类的相关信息.字节码可以看成是数据流,那么方法区的这种数据结构可以说是字节码数据流的结构化表现.装载的最终产物就是java.lang.Class类的一个对象,它是Java程序与方法区内部数据

java多线程详解

转自:线程间通信.等待唤醒机制.生产者消费者问题(Lock,Condition).停止线程和守护线程.线程优先级 1  线程间通信 1.1  线程间通信 其实就是多个线程在操作同一个资源,但是操作的动作不同. 比如一个线程给一个变量赋值,而另一个线程打印这个变量. 1.2  等待唤醒机制 wait():将线程等待,释放了CPU执行权,同时将线程对象存储到线程池中. notify():唤醒线程池中一个等待的线程,若线程池有多个等待的线程,则任意唤醒一个. notifyAll():唤醒线程池中,所有

JAVA: httpclient 详解;

相对于httpurlconnection ,httpclient更加丰富,也更加强大,其中apache有两个项目都是httpclient,一个是commonts包下的,这个是通用的,更专业的是org.apache.http.包下的,所以我一般用后者: httpclient可以处理长连接,保存会话,重连接,以及请求过滤器,连接重用等等... 下面是测试代码(全部总结来自官方文档,以及翻译) 须要下载核心包:httpclient-4.3.4.jar ,也可在官网下载:http://hc.apache