Java基础学习之--理解Object类

看Java API的Object类, 一共11个方法。按使用的频度排名:

  1. toString() 这个方法最常用在打日志,定位代码问题。
  2. equals()hashCode(), 这两个方法的使用经典例子是HashMap的源码
    public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

equals()hashCode() 要常用一点。

  1. wait()notify() 这个开发很少会直接用到,但是间接用到的场景不少,属于偏内功的点。wait/notify属于Object类最难理解的点了,因为它的基石是多线程。学习思路还是三步走。

step 1: 看文档说明

wait()
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.

notify()
Wakes up a single thread that is waiting on this object‘s monitor.

这个文档说明,看完基本一头雾水,两个方法都提到了如下的核心概念thread, object‘s monitor。 先把这些概念放一边,看看是怎么用的。

step 2: 运行Demo

给个demo辅助理解,一个线程是干活的,另一个线程是管事的。管事的等活干完验收。

public class WaitNotifyDemo {

    static class Worker extends Thread{

        private volatile int status=0; // 1: 完成, -1: 出错

        @Override
        public void run(){

            try {
                System.out.println(Thread.currentThread().getName() +": 开始干活");
                Thread.sleep(3000);
                System.out.println(Thread.currentThread().getName() +": 完成任务");

                status = 1;
                // 通知主线程
                synchronized (this){
                    this.notify();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
                status = -1;
            }
        }

        public int getStatus(){
            return status;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Worker worker= new Worker();
        worker.start();

        synchronized (worker){
            int status;
            while ((status=worker.getStatus())!=1){
                worker.wait();
                if(status==-1)
                    throw new RuntimeException("出错了");
            }
        }
        System.out.println("任务已经完成");
    }
}

step3: 折腾demo
接下来, 我试了一下, 把notify的代码去掉,也能正常运行。 这就让人困惑了,文档明明说必须调用notify,wait才能结束。接下来再看文档:

A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup

所以, wait方法必须在while循环中调用。好,解答了一点疑惑。但是每次Worker线程结束时没有调用notify,主线程就能正常退出, 这个也说不通。 唯一的解释是: JVM内部在某个地方调用了notify。看openjdk的源码, 果然如此:从start0开始, 定位到线程在退出时会调用lock.notify_all(thread);。只是这里的代码是JVM内部的代码,比较底层。

其实,这个例子更简洁的写法是worker.join()。 如果看Thread.join()的源码,发现它的实现恰好就是调用了wait。

  1. clone() 这个需要理解深度克隆, 知识点不复杂。
  2. getclass() 这个放在后面,但是用得还挺多的,特别是写框架。
  3. finalize() 这个已经不他推荐使用了, 尽量不干扰GC的节奏。

总结一下,Object类是Java的基石。这里比较难一点的就是wait/notify. 学习Java的API, 如果想理解透彻一点,估计绕不开JVM的c++源码。

原文地址:http://blog.51cto.com/sbp810050504/2328194

时间: 2024-10-12 02:43:32

Java基础学习之--理解Object类的相关文章

黑马程序员--Java基础学习笔记【Object类、String类】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- Object类 在Java类继承结构中,java.lang.Object类位于顶端. 所有类都直接或间接继承Object类. (接口不能继承Object类,接口中隐含定义了Object类的所有公共方法,但是全抽象) Object类型的引用变量可以指向任何类型对象. Object类成员方法 public String toString() { return getClass().getName(

黑马程序员-Java基础-面向对象—多态、Object类、内部类、异常

第一讲  多态 1.  定义 可以理解为事物存在的多种体现形态. 在java中,当函数的功能内容不确定时,可以将此方法定义为抽象方法,让其子类去实现.当子类对象不同时,调用同一个函数名,会执行不同的函数体,得到不同的结果,从而体现了多态性. 2.  多态的体现形式 父类的引用指向了自己的子类对象:Fu f = new Zi(): 父类的引用也可以接受自己的子类对象: 3.  多态的前提条件 必须是类与类之间有关系,要么继承,要么实现(接口): 函数之间存在覆盖(重写): 4.  多态的好处 大大

Java基础学习笔记十二 类、抽象类、接口作为方法参数和返回值以及常用API

不同修饰符使用细节 常用来修饰类.方法.变量的修饰符 public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是一种权限修饰符,默认访问, 类,方法,成员变量 private 权限修饰符,私有访问, 方法,成员变量 static 静态修饰符 方法,成员变量 final 最终修饰符 类,方法,成员变量,局部变量 abstract 抽象修饰符 类 ,方法 我们编写程序时,权限修饰符一般放于所有修饰符之前,不同的权限修饰

java基础学习——19、String类

之前的Java基础系列中讨论了Java最核心的概念,特别是面向对象的基础.在Java进阶中,我将对Java基础进行补充,并转向应用层面. 大部分编程语言都能够处理字符串(String).字符串是有序的字符集合,比如"Hello World!".在Java中,字符串被存储为String类对象.调用字符串对象的方法,可以实现字符串相关的操作. String类包含在java.lang包中.这个包会在Java启动的时候自动import,所以可以当做一个内置类(built-in class).我

JAVA基础学习day17--集合工具类-Collections

一.Collection简述 1.1.Collection与Collections的区别 Collections是集合的静态工具类 Collection:是集合的顶级接口 二.Sort 2.1.sort package com.pb.sort.demo1; import java.util.ArrayList; import java.util.Collections; /** * 对字符串进行自然排序 * */ public class SortDemo1 { public static vo

java基础学习总结——Object类

永不放弃,一切皆有可能!!! 只为成功找方法,不为失败找借口! java基础学习总结——Object类 一.Object类介绍 Object类在JAVA里面是一个比较特殊的类,JAVA只支持单继承,子类只能从一个父类来继承,如果父类又是从另外一个父类继承过来,那他也只能有一个父类,父类再有父类,那也只能有一个,JAVA为了组织这个类组织得比较方便,它提供了一个最根上的类,相当于所有的类都是从这个类继承,这个类就叫Object.所以Object类是所有JAVA类的根基类,是所有JAVA类的老祖宗.

Java基础学习191221(可变参数,数组,Array类,稀疏数组,继承重写多态,抽象类,接口)

Java基础学习 可变参数 在方法声明中,在指定参数类型后加一个省略号(...). 一个方法中只能指定一个可变参数,它必须是方法的最后一个参数.任何普通参数都必须在它之前声明. public class printMax { public static void main(String[] args) { printMax(1,5,8,78,415,15); } public static void printMax( double... numbers){ if (numbers.length

Java 基础:认识&理解关键字 native 实战篇

Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 泥瓦匠初次遇见 navicat 是在 java.lang.Object 源码中的一个hashCode方法: 1 public native int hashCode(); 为什么有个navicat呢?这是我所要学习的地方.所以今天泥瓦匠想要总结下navicat. 一.认识 native 即 JNI,Java Native Interface 凡是一种语言,都希望是纯.比如解决某一个方案都喜欢就单单这

Java基础学习总结——Java对象的序列化和反序列化

一.序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化. 把字节序列恢复为对象的过程称为对象的反序列化. 对象的序列化主要有两种用途: 1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中: 2) 在网络上传送对象的字节序列. 在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便长期保存.比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些s