- 浏览: 163353 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
zhousheng193:
非常感谢LZ
在JSP页面及servlet的doGet()方法中处理汉字乱码的问题 -
jie523314:
学习下。。。
读取XML文件
引用
当我们写一个类的时候,都会对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()会被再次调用。
请看下面的示例:
运行结果如下:
• 执行了finalize()方法
程序调用了java.lang.System类的gc()方法,引起GC的执行,GC在清理ft对象时调用了它的finalize()方法,因此才有了上面的输出结果。调用System.gc()等同于调用下面这行代码:
Java代码
Runtime.getRuntime().gc();
调用它们的作用只是建议垃圾收集器(GC)启动,清理无用的对象释放内存空间,但是GC的启动并不是一定的,这由JAVA虚拟机来决定。直到 JAVA虚拟机停止运行,有些对象的finalize()可能都没有被运行过,那么怎样保证所有对象的这个方法在JAVA虚拟机停止运行之前一定被调用呢?答案是我们可以调用System类的另一个方法:
Java代码
给这个方法传入true就可以保证对象的finalize()方法在JAVA虚拟机停止运行前一定被运行了,不过遗憾的是这个方法是不安全的,它会导致有用的对象finalize()被误调用,因此已经不被赞成使用了。
由于finalize()属于Object类,因此所有类都有这个方法,Object的任意子类都可以重写(override)该方法,在其中释放系统资源或者做其它的清理工作,如关闭输入输出流。
六 wait()/notify()/notifyAll()
通常,多线程之间需要协调工作。例如,浏览器的一个显示图片的线程displayThread想要执行显示图片的任务,必须等待下载线程 downloadThread将该图片下载完毕。如果图片还没有下载完,displayThread可以暂停,当downloadThread完成了任务后,再通知displayThread“图片准备完毕,可以显示了”,这时,displayThread继续执行。
以上逻辑简单的说就是:如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify.等待机制与锁机制是密切关联的。例如:
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
需要注意的概念是:
◆调用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中的一个才有机会获得锁继续执行。
一 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(); } }
运行结果如下:
• 执行了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 }
给这个方法传入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(); }
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A:
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中的一个才有机会获得锁继续执行。
发表评论
-
举例讲解线程的wait()和notify()
2010-10-10 09:59 995通常,多线程之间需要协调工作,例如两个人公用一个卫生间(每次只 ... -
3种常见的设计模式
2010-09-30 14:01 973工厂模式: 引用 定义一个创建产品对象的工厂类,由该工厂统 ... -
Eclipse6.0 代码提示(代码助手) 设置方法
2010-08-30 09:53 1386在MyEclipse6.0的快捷键中 ... -
Byte[]数组与其他数据类型相互转换
2010-07-22 18:53 887Byte[]数组与其他数据类型相互转换 //Byte[ ... -
byte[] 转换成 int
2010-07-22 18:33 1074一个完整的byte[]转换成int byte[] b= n ... -
用java对图片进行绘画
2010-07-07 09:28 932package com.java.test_IO; im ... -
怎么用java删除父文档及子文档
2010-07-06 19:16 1043package org.tarena.day01; ... -
我的收藏网址
2010-06-29 17:36 602纯属个人收藏,不知道的不要乱点!! 引用 swing组件的使用 ... -
JAVA面试题-CORE JAVA部分
2010-06-28 21:10 1830引用1.在main(String[] args ... -
五种常见的异常
2010-06-25 18:52 787引用五种常见的异常 package day14.tar ... -
理解Java 抽象类(abstract Class)与接口(interface)
2010-06-25 11:30 989abstract class 和interface是J ... -
理解final,finally,finalize三者区别
2010-06-25 09:28 1881final关键字 我们首先来说说final。它可以用于以下四个 ... -
Java面试问题
2010-06-24 21:01 1480引用Java常见面试题集锦 ... -
浅克隆和深克隆的理解和区别
2010-06-24 20:21 2629引用 今天,和同学讨论了下java的clone( ... -
用户登录界面代码
2010-06-24 09:38 3052引用注:这只是个登录测试参考,是练习知识点用的, 具体功能不完 ... -
猜数字游戏
2010-06-23 21:01 784package org.text.day01; impo ... -
简易计算器
2010-06-23 20:05 734package org.tarena.day01; im ... -
java图片浏览器(娱乐)
2010-06-23 19:58 1835package org.tarena.day02; im ...
相关推荐
#### 一、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()`方法反序列化类。每种方法都有其适用场景和局限...