Java Object类方法总结

Java Object类方法

Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起。Object类位于java.lang包中,java.lang包包含着Java最基础和核心的类,在编译时会自动导入。Object类没有定义属性,一共有13个方法,具体的类定义结构如下图:

Java Object类方法总结

1.类构造器public Object();

大部分情况下,Java中通过形如 new A(args…)形式创建一个属于该类型的对象。其中A即是类名,A(args…)即此类定义中相对应的构造函数。通过此种形式创建的对象都是通过类中的构造函数完成。
为体现此特性,Java中规定:在类定义过程中,对于未定义构造函数的类,默认会有一个无参数的构造函数,作为所有类的基类,Object类自然要反映出此特性,在源码中,未给出Object类构造函数定义,但实际上,此构造函数是存在的。
当然,并不是所有的类都是通过此种方式去构建,也自然的,并不是所有的类构造函数都是public。

2.private static native void registerNatives();

registerNatives函数前面有native关键字修饰,Java中,用native关键字修饰的函数表明该方法的实现并不是在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用。

3.protected native Object clone() throws CloneNotSupportedException;

clone()方法又是一个被声明为native的方法,因此,我们知道了clone()方法并不是Java的原生方法,具体的实现是有C/C++完成的。clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。所以此时,对原来的对象进行操作并不影响clone出来的对象。

4.public final native Class<?> getClass();

返回的是此Object对象的类对象;
“类对象"的概念:作为概念层次的类,其本身也具有某些共同的特性,如都具有类名称、由类加载器去加载,都具有包,具有父类,属性和方法等。于是,Java中有专门定义了一个类,Class,去描述其他类所具有的这些特性,因此,从此角度去看,类本身也都是属于Class类的对象。为与经常意义上的对象相区分,在此称之为"类对象”。

5.public boolean equals(Object obj);

==与equals的区别:
==表示的是变量值完成相同(对于基础类型,地址中存储的是值,引用类型则存储指向实际对象的地址);
equals表示的是对象的内容完全相同,此处的内容多指对象的特征/属性。
实际上,上面说法是不严谨的,更多的只是常见于String类中。首先看一下Object类中关于equals()方法的定义:

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

由此可见,Object原生的equals()方法内部调用的正是"= =(等于) “与 " = = “具有相同的含义。既然如此,为什么还要定义此equals()方法?
equlas()方法的正确理解应该是:判断两个对象是否相等。那么判断对象相等的标尺又是什么?
如上,在object类中,此标尺即为” = =”。当然,这个标尺不是固定的,其他类中可以按照实际的需要对此标尺含义进行重定义。如String类中则是依据字符串内容是否相等来重定义了此标尺含义。如此可以增加类的功能型和实际编码的灵活性。当然了,如果自定义的类没有重写equals()方法来重新定义此标尺,那么默认的将是其父类的equals(),直到object基类。
如下场景的实际业务需求,对于User bean,由实际的业务需求可知当属性uid相同时,表示的是同一个User,即两个User对象相等。则可以重写equals以重定义User对象相等的标尺。

package com.corn.objectsummary;
 2 
 3 public class User {
 4 
 5     private int uid;
 6     private String name;
 7     private int age;
 8 
 9     public int getUid() {
10         return uid;
11     }
12 
13     public void setUid(int uid) {
14         this.uid = uid;
15     }
16 
17     protected String getName() {
18         return name;
19     }
20 
21     public void setName(String name) {
22         this.name = name;
23     }
24 
25     public int getAge() {
26         return age;
27     }
28 
29     public void setAge(int age) {
30         this.age = age;
31     }
32 
33     @Override
34     public boolean equals(Object obj) {
35         if (obj == null || !(obj instanceof User)) {
36             return false;
37         }
38         if (((User) obj).getUid() == this.getUid()) {
39             return true;
40         }
41         return false;
42     }
43 }


     package com.corn.objectsummary;
  
  public class ObjectTest implements Cloneable {
  
     public static void main(String[] args) {
          User u1 = new User();
            u1.setUid(111);
            u1.setName("张三");
            User u2 = new User();
            u2.setUid(111);
            u2.setName("张三丰");
           System.out.println(u1.equals(u2)); //返回true
     }
 }

ObjectTest中打印出true,因为User类定义中重写了equals()方法,这很好理解,很可能张三是一个人小名,张三丰才是其大名,判断这两个人是不是同一个人,这时只用判断uid是否相同即可。

如上重写equals方法表面上看上去是可以了,实则不然。因为它破坏了Java中的约定:重写equals()方法必须重写hasCode()方法。

6 public native int hashCode();

HashCode();
返回一个integer类型的值,这个值是通过该Object的内部地址(internal address)转换过来的,这个哈希码是可以通过getClass()方法看到具体值的,显示的是十六进制的数,有时候可以通过此方法来判断对象的引用是否相等。

hashCode()具有如下约定:

1).在Java应用程序程序执行期间,对于同一对象多次调用hashCode()方法时,其返回的哈希码是相同的,前提是将对象进行equals比较时所用的标尺信息未做修改。在Java应用程序的一次执行到另外一次执行,同一对象的hashCode()返回的哈希码无须保持一致;

2).如果两个对象相等(依据:调用equals()方法),那么这两个对象调用hashCode()返回的哈希码也必须相等;

3).反之,两个对象调用hasCode()返回的哈希码相等,这两个对象不一定相等。
即:两个对象相等 <=> equals()相等 => hashCode()相等。
对象的hashCode()返回的不是对象所在的物理内存地址。甚至也不一定是对象的逻辑地址,hashCode()相同的两个对象,不一定相等,换言之,不相等的两个对象,hashCode()返回的哈希码可能相同。

7.public String toString();

toString()方法返回该对象的字符串表示。先看一下Object中的具体方法体:

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

toString()方法相信大家都经常用到,即使没有显式调用,但当我们使用System.out.println(obj)时,其内部也是通过toString()来实现的。
getClass()返回对象的类对象,getClassName()以String形式返回类对象的名称(含包名)。Integer.toHexString(hashCode())则是以对象的哈希码为实参,以16进制无符号整数形式返回此哈希码的字符串表示形式。
toString()是由对象的类型和其哈希码唯一确定,同一类型但不相等的两个对象分别调用toString()方法返回的结果可能相同。

7.wait()/notify()/notifyAll()

wait()在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
wait(long timeout)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
wait(long timeout, int nanos)在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。

notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有的线程。
我们应该在某个线程获取对象的锁后,在该对象锁控制的同步块或同步方法中去调用该对象的wait方法,将该线程挂起放入该对象等待队列。

因为wait需释放锁,所以必须在synchronized中使用(没有锁定则么可以释放?没有锁时使用会抛出IllegalMonitorStateException(正在等待的对象没有锁))
当调用该对象的notify方法时,将从该对象的等待队列中随机唤醒一个线程,这个线程将再次成为可运行的线程。

所以我们使用wait和notify方法的时候必须确定这两个线程在同一个对象(必须是控制该同步块或同步方法的对象)的等待队列。

13.protected void finalize();

finalize方法主要与Java垃圾回收机制有关。首先我们看一下finalized方法在Object中的具体定义:

 protected void finalize() throws Throwable { }

我们发现Object类中finalize方法被定义成一个空方法,为什么要如此定义呢?finalize方法的调用时机是怎么样的呢?

首先,Object中定义finalize方法表明Java中每一个对象都将具有finalize这种行为,其具体调用时机在:JVM准备对此对形象所占用的内存空间进行垃圾回收前,将被调用。由此可以看出,此方法并不是由我们主动去调用的(虽然可以主动去调用,此时与其他自定义方法无异)。

参考一下文档:

Java中Object类的公有方法

Java总结篇系列:java.lang.Object

欢迎使用Markdown编辑器

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

新的改变

我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:

  1. 全新的界面设计 ,将会带来全新的写作体验;
  2. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
  3. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
  4. 全新的 KaTeX数学公式 语法;
  5. 增加了支持甘特图的mermaid语法1 功能;
  6. 增加了 多屏幕编辑 Markdown文章功能;
  7. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
  8. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Java Object类方法总结

带尺寸的图片: Java Object类方法总结

居中的图片: Java Object类方法总结

居中并且带尺寸的图片: Java Object类方法总结

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目 Value
电脑 $1600
手机 $12
导管 $1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文本居中 第二列文本居右 第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to-HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ(n)=(n1)!nN\Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通过欧拉积分

Γ(z)=0tz1etdt&ThinSpace;. \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

你可以找到更多关于的信息 LaTeX 数学表达式[here][1].

新的甘特图功能,丰富你的文章

Mon 06Mon 13Mon 20已完成 进行中 计划一 计划二 现有任务Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 [这儿][2],

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三李四王五你好!李四, 最近怎么样?你最近怎么样,王五?我很好,谢谢!我很好,谢谢!李四想了很长时间,文字太长了不适合放在一行.打量着王五...很好... 王五, 你怎么样?张三李四王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 [这儿][3],

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.2.0开始我的操作确认?结束yesno
  • 关于 Flowchart流程图 语法,参考 [这儿][4].

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎