- 浏览: 279936 次
- 性别:
- 来自: 厦门
文章分类
最新评论
-
chenxliang:
2016年10月26、27日,上海浦东,Postgres中国用 ...
用JDBC连接Postgres(Postgres学习笔记1) -
cuiran:
不错,讲的很详细。
web.xml 中的listener、 filter、servlet 加载顺序及其详解 -
i_am_birdman:
PostgreSQL的管理启动服务pg_ctl -D /pat ...
PostgreSql 数据库备份恢复 删除 建立 -
i_am_birdman:
songshuang 写道现在觉悟也不晚!加油!
加油呵呵
人生规划啊 -
songshuang:
现在觉悟也不晚!加油!
人生规划啊
当我们写一个类的时候,都会对Java.lang.Object类的一些重要方法进行重写,这些方法包含:hashCode(),toString(),equals(),finalize(),clone()
,wait(),notify()/notifyAll() 这八个方法。
一 Equals()方法:
1.何时需要重写equals()
当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念)。
2.设计equals()
[1]使用instanceof操作符检查“实参是否为正确的类型”。
[2]对于类中的每一个“关键域”,检查实参中的域与当前对象中对应的域值。
[2.1]对于非float和double类型的原语类型域,使用==比较;
[2.2]对于对象引用域,递归调用equals方法;
[2.3]对于float域,使用Float.floatToIntBits(afloat)转换为int,再使用==比较;
[2.4]对于double域,使用Double.doubleToLongBits(adouble) 转换为long,再使用==比较;
[2.5]对于数组域,调用Arrays.equals方法。
二 hashCode()方法:
1.当改写equals()的时候,总是要改写hashCode()
根据一个类的equals方法(改写后),两个截然不同的实例有可能在逻辑上是相等的,但是,根据Object.hashCode方法,它们仅仅是两个对象。因此,违反了“相等的对象必须具有相等的散列码”。
2.设计hashCode()
[1]把某个非零常数值,例如17,保存在int变量result中;
[2]对于对象中每一个关键域f(指equals方法中考虑的每一个域):
[2.1]boolean型,计算(f ? 0 : 1);
[2.2]byte,char,short型,计算(int);
[2.3]long型,计算(int) (f ^ (f>>>32));
[2.4]float型,计算Float.floatToIntBits(afloat);
[2.5]double型,计算Double.doubleToLongBits(adouble)得到一个long,再执行[2.3];
[2.6]对象引用,递归调用它的hashCode方法;
[2.7]数组域,对其中每个元素调用它的hashCode方法。
[3]将上面计算得到的散列码保存到int变量c,然后执行 result=37*result+c;
[4]返回result。
三 toString()方法:
toString方法我们处处都用到,是一个很重点的小知识,这里大概讲一下:
我们查阅API文档,查看java.lang.Object类的toString方法的详细描述是这样的:
toString
public String toString()
Returns a string representation of the object. In general, the
toString method returns a string that "textually represents" this
object. The result should be a concise but informative representation
that is easy for a person to read. It is recommended that all subclasses
override this method.
The toString method for class Object returns a string consisting of
the name of the class of which the object is an instance, the at-sign
character `@', and the unsigned hexadecimal representation of the hash
code of the object. In other words, this method returns a string equal
to the value of:
getClass().getName() + '@' + Integer.toHexString(hashCode())
Returns:
a string representation of the object.
我们大概翻译一下:
返回一个能够代表这个对象的字符串。一般而言,toString方法返回这个对象的“文本表达式”。这个返回的结果很简洁但是不是易于人们阅读的信息表达式。这里推荐大家在使用的子类的时候重写该方法。
对于Object这个类而言,toString方法返回值是由所属类的类名、一个“@”符号和这个对象哈希码的无符号十六进制表达式组成的。换句话说,这个方法返回的字符串等同于下面的方法返回的值:
getClass().getName()+ '@' + Integer.toHexString(hashCode())
返回:
这个对象的字符串表达式
我们再看看java.lang.String类中的toString方法,看看是否一样呢
toString
public String toString()
This object (which is already a string!) is itself returned.
Specified by:
toString in interface CharSequence
Overrides:
toString in class Object
Returns:
the string itself.
我们还是翻译一下吧:
这个对象自己(它已经是一个字符串了)就是返回值
说明:
CharSequence接口中的toString方法
重写:
重写了Object中的toString方法
返回:
自己本身的字符串
我们可以看到,String类继承Object类,并且重写了toString方法,也就是说他有自己的toString方法,它返回一个自己本身的字符串,而自己本身就是字符串对象,这样就不会出现一推哈希码了。
在这里为了更加明确,我们从“说明”中看到,String中toString方法是CharSequence接口的toString方法,那我们看一看java.lang.CharSequence接口的toString方法的定义:
toString
String toString()
Returns a string containing the characters in this sequence in the
same order as this sequence. The length of the string will be the length
of this sequence.
Overrides:
toString in class Object
Returns:
a string consisting of exactly this sequence of characters
我们还是翻译一下:
返回一个字符串,该字符串包含了与这个序列顺序相同的所有字符。字符串的长度就是该序列的长度
重写:
Object的toString
返回:
由该序列的特定的字符组成的字符串
四 clone()方法:
对于克隆(Clone),Java有一些限制:
1、被克隆的类必须自己实现Cloneable 接口,以指示 Object.clone() 方法可以合法地对该类实例进行按字段复制。Cloneable 接口实际上是个标识接口,没有任何接口方法。
2、实现Cloneable接口的类应该使用公共方法重写 Object.clone(它是受保护的)。
3、在Java.lang.Object类中克隆方法是这么定义的:
protected Object clone() throws CloneNotSupportedException
创建并返回此对象的一个副本。表明是一个受保护的方法,同一个包中可见。
按照惯例,返回的对象应该通过调用 super.clone 获得。
浅拷贝:指的是你的类本身被拷贝,而没有拷贝类本身属性中的类。
深拷贝:指的是包含类本身和属性类在内的所有类的拷贝。
简单点说:就是浅拷贝的两个对象中的属性还会指向同一个类,而深拷贝则全部单独了。也就是说深拷贝把关联关系也拷贝了。可以简单理解为深拷贝中的数据类型中含有类类型的变量,因为java中传递参数的形式是以传值方式进行的。
五 finalize()方法:
protected void finalize() throws Throwable { }:众所周知,finalize()方法是GC(garbage collector)运行机制的一部分
finalize()方法是在GC清理它所从属的对象时被调用的,如果执行它的过程中抛出了无法捕获的异常(uncaught
exception),GC将终止对改对象的清理,并且该异常会被忽略;直到下一次GC开始清理这个对象时,它的finalize()会被再次调用。
请看下面的示例:
- Java代码
- public final class FinallyTest {
- // 重写finalize()方法
- protected void finalize() throws Throwable {
- System.out.println("执行了finalize()方法" );
- }
- public static void main(String[] args) {
- FinallyTest ft = new FinallyTest();
- ft = null ;
- System.gc();
- }
- }
Java代码 public final class FinallyTest { // 重写finalize()方法 protected void finalize() throws Throwable { System.out.println("执行了finalize()方法"); } public static void main(String[] args) { FinallyTest ft = new FinallyTest(); ft = null; System.gc(); } }
运行结果如下:
• 执行了finalize()方法
程序调用了java.lang.System类的gc()方法,引起GC的执行,GC在清理ft对象时调用了它的finalize()方法,因此才有了上面的输出结果。调用System.gc()等同于调用下面这行代码:
Java代码
Runtime.getRuntime().gc();
调用它们的作用只是建议垃圾收集器(GC)启动,清理无用的对象释放内存空间,但是GC的启动并不是一定的,这由JAVA虚拟机来决定。直到
JAVA虚拟机停止运行,有些对象的finalize()可能都没有被运行过,那么怎样保证所有对象的这个方法在JAVA虚拟机停止运行之前一定被调用
呢?答案是我们可以调用System类的另一个方法:
Java代码
- public static void runFinalizersOnExit( boolean value) {
- //other code
- }
public static void runFinalizersOnExit(boolean value) { //other code }
给这个方法传入true就可以保证对象的finalize()方法在JAVA虚拟机停止运行前一定被运行了,不过遗憾的是这个方法是不安全的,它会导致有用的对象finalize()被误调用,因此已经不被赞成使用了。
由于finalize()属于Object类,因此所有类都有这个方法,Object的任意子类都可以重写(override)该方法,在其中释放系统资源或者做其它的清理工作,如关闭输入输出流。
六 wait()/notify()/notifyAll()
通常,多线程之间需要协调工作。例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程
downloadThread将该图片下载完毕。如果图片还没有下载完,displayThread可以暂停,当downloadThread完成了任务
后,再通知displayThread“图片准备完毕,可以显示了”,这时,displayThread继续执行。
以上逻辑简单的说就是:如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify.等待机制与锁机制是密切关联的。例如:
- synchronized (obj) {
- while (!condition) {
- obj.wait();
- }
- obj.doSomething();
- }
synchronized(obj) { while(!condition) { obj.wait(); } obj.doSomething(); }
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
- synchronized (obj) {
- condition = true ;
- obj.notify();
- }
synchronized(obj) { condition = true; obj.notify(); }
需要注意的概念是:
◆调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj) {……} 代码段内。
◆调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj) {……} 代码段内唤醒A。 ◆当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。
◆如果A1,A2,A3都在obj.wait(),则B调用obj.notify()只能唤醒A1,A2,A3中的一个(具体哪一个由JVM决定)。
◆obj.notifyAll()则能全部唤醒A1,A2,A3,但是要继续执行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3只有一个有机会获得锁继续执行,例如A1,其余的需要等待A1释放obj锁之后才能继续执行。
◆当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,但是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续执行。
发表评论
-
Thinking in java 读书笔记
2012-03-13 09:32 0面向对象语言的5个特性: 1.万物皆为对象。 2.程序是对象的 ... -
java应用打包jar,jar转换exe
2012-02-13 10:16 927java projects 打包jar的方法: (1):用ec ... -
几种基本的数字正则表达式
2011-04-06 20:20 1250只能输入1个数字 表达式 ^\d$ 描述 ... -
坚持着
2010-12-26 22:35 795有时候不知道为什么,明明知道没有希望,没有意义,还是要坚持,为 ... -
JDK自带的native2ascii工具
2010-12-15 10:40 715背景:java默认的编码方式为Unicode,而计算机系统编码 ... -
对象的序列化和反序列化
2010-12-06 20:22 793当两个进程在进行远程 ... -
Java的序列化机制
2010-12-06 20:22 807Java的序列化机制只序列化对象的属性值,而不会去序列化什么所 ... -
浅谈异常处理
2010-12-06 12:46 625六种异常处理的陋习 你觉得自己是一个Java专家吗?是否肯定 ... -
java.io.Reader和java.io.Writer
2010-11-11 10:33 136414.3 字符流 java.io.Reader、java ... -
Java 反射机制深入研究
2010-11-06 17:50 797Java 反射是Java语言的一个很重要的特征,它使得Java ... -
Abstract Class and Interface 抽象类与接口的区别
2010-11-03 19:58 1131abstract Methods and Classes -- ... -
关于String,StringBuffer,StringBuilder,+和append
2010-09-14 15:17 882String一旦赋值或实例化后就不可更改,如果赋予新值将会重新 ... -
关于对象的equal方法和hashCode方法
2010-09-08 13:28 1329equal方法 Object类的equals方法用于检测一个对 ... -
arraylist的使用方法
2010-06-19 21:08 9881、什么是ArrayList ArrayList ... -
myeclipse基本设置
2010-06-15 15:26 12071.myeclipse如何显示行数 Window->P ... -
Java多线程编程要点 (二)
2010-06-14 13:20 7824、 Timer 和 Timer Task 的 ... -
Java多线程编程要点 (一)
2010-06-14 13:17 7561、 认识Thread和Runnable Java中实现多线程 ... -
String.valueOf()
2010-06-14 13:00 4051String.valueOf()是把java的原始数据类型或运 ... -
一些基础
2010-06-11 19:39 7791 notify与notifyall的区别 notify和no ...
相关推荐
#### 一、Object类常用方法 在Java中,`Object`类是最基础的类,所有其他类都直接或间接继承自它。因此了解并掌握`Object`类的方法对于深入理解Java编程至关重要。 1. **toString() 方法**: - **用途**:提供了...
内容概要 这个源码资源是关于Java中的Object类的讲解案例代码。Object类是所有Java类的根类...理解equals()、hashCode()、toString()等常用方法的用途。 学会正确重写这些方法,以满足特定需求。应用实例代码中提供的场
# Java核心知识点详解:Object类与常用API ## Object类概览 ### 1.1 概述 在Java编程语言中,`java.lang.Object`类具有非常特殊的地位,它是所有Java类的基类,即使程序员没有明确地指定某个类继承自`Object`类,...
Object 类常用方法 Object 类是 Java 语言中的顶层类,是所有类的直接或间接父类。任何类,如果没有书写 extends 显式继承某个类,都默认直接继承 Object 类,否则为间接继承。Object 类中所定义的方法,是所有对象...
### Object类和Scanner类 #### 一、Object类详解 ...通过以上介绍可以看出,`Object` 类和 `Scanner` 类分别代表了Java中对象的基本行为和简单的输入处理功能,它们都是Java编程不可或缺的一部分。
【Java基础知识-day01【Object类、常用API】】 在Java编程中,了解和掌握Object类及其常用API是至关重要的,因为所有Java类都间接或直接地继承自Object类。本章将深入探讨Object类的一些核心方法,如toString()和...
JAVA 中有许多常用的类,每个类都有其特定的方法,本文将对 java.lang.Object 类、String 类和 StringBuffer 类的常用方法进行讲解。 一、java.lang.Object类 java.lang.Object 类是 JAVA 中所有类的父类,它提供...
在Java编程中,Object类的方法非常重要,常见的如getClass()、toString()和equals()。 1. getClass()方法: 这个方法用于获取运行时对象的类类型。这个方法返回的是一个Class类型的对象,它代表了对象的类型信息。...
Java中的`Object`类是所有Java类的根类,无论你定义...对于自定义类,根据业务需求重写`equals()`方法是常见的做法,以确保比较的是对象的内容而非引用。正确理解和使用`equals()`方法对于编写健壮的Java代码至关重要。
Java 中的 equals 方法是一种用于比较对象是否相等的方法,它是 Object 类中的一个方法。然而,重写 equals 方法并不是一件简单的事情,因为它需要遵守一些约定,否则可能会出现一些不可预期的行为。在这篇文章中,...
Object类中定义了native修饰的方法,称为本地方法,本地方法的特点是被native修饰的方法,非Java语言编写,是由C++语言编写。本地方法在运行时期进入本地方法栈内存,本地方法栈是一块独立内存的区域。本地方法的...
Java SE编程入门涉及众多基础知识,这里我们主要关注Java对象、Object类及其常用方法。Java语言是一种面向对象的编程语言,所有类都直接或间接地继承自Object类,它位于核心库`java.lang`包中。 1. **Object类**: ...
在Java中,`Object`类是所有类的父类,它提供了几个核心的方法,包括`equals()`, `hashCode()`, 和 `toString()`。 `equals()`方法用于比较两个对象是否相等。默认实现比较的是对象的引用,即两个对象是否指向内存...
- 例如,`Car`类有一个`drive()`方法,`ElectricCar`继承自`Car`并重写了`drive()`方法,当调用`ElectricCar`对象的`drive()`时,执行的是`ElectricCar`类中的版本。 5. **抽象类与接口**: - 抽象类不能被实例化...
在Java编程语言中,`Object`类是一个非常关键的类,它...总的来说,理解和掌握`Object`类及其方法、垃圾回收机制、包装类和`String`类以及内部类的使用,对于深入理解Java编程至关重要,也是初学者必须掌握的基础知识。
本文介绍了Java中实例化类的四种常用方法:使用`new`操作符、调用`Class`对象的`newInstance()`方法、调用`clone()`方法以及通过`ObjectInputStream`的`readObject()`方法反序列化类。每种方法都有其适用场景和局限...