黑马程序员技术交流社区

标题: 有个问题不太清楚啊,大家解答一下啊? [打印本页]

作者: 乔叶旭    时间: 2012-11-26 22:18
标题: 有个问题不太清楚啊,大家解答一下啊?
本帖最后由 乔叶旭 于 2012-11-27 21:32 编辑

在定义类时,何时需要重写Object 类中toString()方法何时需要重写Object类中equals()方法呢?
作者: 宫明星    时间: 2012-11-26 22:31
本帖最后由 宫明星 于 2012-11-26 22:35 编辑

当需要自己设定返回的字符串的形势和内容的时候可以重写toString
比如当某个对象和String相连的时候,有时候系统提供的toString不能满足要求,这个时候需要重写toString方法,来实现特定的功能,否则可能会打印引用地址之类的信息

需要自己定义比较方式的时候重写equals方法。
比如说,如果默认的比较方式是按字符abc比较的,那么你想换一种比较方式,那么就可以重写equals。
作者: 崔维友    时间: 2012-11-26 22:41
        简单说就是需要的时候。啰嗦点就是继承来的toString()和equals()不能满足需要的时候。
        toString方法主要用于打印对象的现有信息。实际是getClass().getName() + '@' + Integer.toHexString(hashCode()) ,返回字符串。你可以根据自己的需要重写。比如直接返回字符串“return Just return a string.”。
       equals方法主要做比较用,比如字符串。当其默认的按自然顺序比较不能满足需要时就得重写,如按照长度排序。当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
        具体参阅API。
--------------------------
不才拙见,敬请指正。

作者: 马超happy519    时间: 2012-11-26 23:34
Object类默认是所有引用类的父类,所有引用类型都继承了Object中的toString()方法。toString()方法的功能是返回当前对象的字符串表示,该方法可以很方便地将引用类型转换为字符串类型。toString()方法的定义格式为:public String toString()。toString()方法返回的字符串格式由类名、“@”符和对象散列码的无符号十六进制表示组成,具体格式为:getClass().getName()+’@’+Interger.toHexString(hashCode())。
例如:
public class DemotoString
{
        public static void main(String[] args)
        {
                Demo demo = new Demo();
                System.out.println(demo.toString());
        }
}

class Demo
{
}
其输出为:
Demo@61de33
如果不满意toString()方法返回的字符串格式,可以在子类中重写该方法。在JDK帮助文档中,也建议所有的子类根据需要都重写此方法。
例:
public class Person
{
   private String name;
   private int age;
   private String sex;

   public String getName()
   {
    return name;  
   }

   public void setName(String name)
   {
       this.name = name;
   }

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

   public int getAge()
   {
       return age;
   }

   public String getSex()
   {
       return sex;
   }

   public void setSex(String sex)
   {
       this.sex = sex;
   }

   ///覆盖toString()方法
   public String toString()
   {
       return getClass()+ "["+"name="+name+",age="+age+",sex="+sex+"]";
   }

   public static void  main(String args[])

   {
       Person p = new Person();
       p.setName("帕奎奥");
       p.setAge(30);
       p.setSex("男");
       System.out.println(p.toString());
   }
}
输出为:class Person[name=帕奎奥,age=30,sex=男]

equals()也是Object类中提供的方法之一。首先看看Object equals()在Java中的原代码:
public boolean equals(Object obj) {
        return (this == obj);
}
可以看出,只有当一个实例等于它本身的时候,equals()才会返回true值。通俗地说,此时比较的是两个引用是否指向内存中的同一个对象,也可以称做是否实例相等。而我们在使用equals()来比较两个指向值对象的引用的时候,往往希望知道它们逻辑上是否相等,而不是它们是否指向同一个对象。在这样的情况下, 如果超类也没有重写equals()以实现期望的行为,这时我们就需要重写equals方法。
Object仅仅提供了一个对引用的比较,如果两个引用不是同一个那就返回false,这是无法满足大多数对象比较的需要的,所以要覆盖。
作者: 徐大鹏    时间: 2012-11-26 23:42
Object类中四个常需要重写的方法


public class Object

类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。 java.lang.Object

_______________________________________________

hashCode 的常规协定是:

* 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
* 如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
返回:
此对象的一个哈希码值。


_______________________________________________


equals()方法是在Object类中定义的方法,它的声明格式为:

public boolean equals(Object obj)

指示某个其他对象是否与此对象“相等”。

equals 方法在非空对象引用上实现相等关系:

* 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
* 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
* 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
* 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
* 对于任何非空引用值 x,x.equals(null) 都应返回 false。

Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

操作符"=="两边操作元可以简单类型也可是引用类型,当两边都是简单类型时,比较的是栈里面的值(value),当两边是引用类型时,比较的是两个引用类型变量
保存的地址,即两个引用变量都引用同一个对象,结果才为true.
(注意:"=="可以用于数组类型)

当创建的两个引用类型对象objec1,object2有相同的属性时,可以重写equals()方法,使 objec1.equals(object2) 的结果为true.

public class Person { //写一个Person类
private int id;
private String name;
public int hashCode() { //重写哈希码以维护 hashCode 方法的常规协定,相等对象必须具有相等的哈希码。
int temp = 23; //写一个随意的变量作为类标识
return temp+this.id*43; //防止子类哈希码的重复
}

//重写一个equals()方法,当Person类型对象有相同的id时返回true

public boolean equals(Object otherobject) { //指示某个其他对象是否与此对象otherobject“相等”
if(this==otherobject) //自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true
return true;
if(otherobject==null) //对于任何非空引用值 x,x.equals(null) 都应返回 false
return false;
if(getClass().getName() != otherobject.getClass().getName()) //必须是相同引用类型对象间比较
return false;

if(!(otherobject instanceof Person)) //判断otherobject是否是Person类型
return false;
Person other = (Person)otherobject; //多态还原
return id == other.id; //id相等返回true,否则返回false
}

public String toString() {
return getId()+": "+getName();
}

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}

/**这个似乎重写也可以的,但是逻辑不强
*public boolean equals(Object obj){
* if(obj == null){
* return false;
* }else if(obj instanceof Person){ //判断obj是否是Person类型
* Person s1 = (Person)obj; //多态还原
* return this.id == s1.getId();
* }else{
* return false;
* }
* }
*/

注意:当equals()方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

_______________________________________________

clone

protected Object clone()
throws CloneNotSupportedException

创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。一般来说,对于任何对象 x,如果表达式:

x.clone() != x

是正确的,则表达式:

x.clone().getClass() == x.getClass()

将为 true,但这些不是绝对条件。一般情况下是:

x.clone().equals(x)

将为 true,但这不是绝对条件。

按照惯例,返回的对象应该通过调用 super.clone 获得。如果一个类及其所有的超类(Object 除外)都遵守此约定,则 x.clone().getClass() == x.getClass()。

按照惯例,此方法返回的对象应该独立于该对象(正被克隆的对象)。要获得此独立性,在 super.clone 返回对象之前,有必要对该对象的一个或多个字段进行修改。这通常意味着要复制包含正在被克隆对象的内部“深层结构”的所有可变对象,并使用对副本的引用替换对这些对象的引用。如果一个类只包含基本字段或对不变对象的引用,那么通常不需要修改 super.clone 返回的对象中的字段。

Object 类的 clone 方法执行特定的克隆操作。首先,如果此对象的类不能实现接口 Cloneable,则会抛出 CloneNotSupportedException。注意:所有的数组都被视为实现接口 Cloneable。否则,此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;这些字段的内容没有被自我克隆。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。

Object 类本身不实现接口 Cloneable,所以在类为 Object 的对象上调用 clone 方法将会导致在运行时抛出异常。

返回:
此实例的一个克隆。
抛出:
CloneNotSupportedException - 如果对象的类不支持 Cloneable 接口,则重写 clone 方法的子类也会抛出此异常,以指示无法克隆某个实例。

_______________________________________________


toString

public String toString()
返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂。建议所有子类都重写此方法。
Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
getClass().getName() + '@' + Integer.toHexString(hashCode())


返回:
该对象的字符串表示形式。
例子:
public class TestClone implements Cloneable{ //类可以被clone
private int temp = 0;
private String name = new String("**copy**");
//浅clone不需要重写,深clone需要重写
public static void main(String[] args) throws Exception{
TestClone tc = new TestClone();
TestClone o = (TestClone)tc.clone();
System.out.println(tc == o);//clone对象和源对象比较
System.out.println(tc.name==o.name);
//浅拷贝原样复制,拷贝出来的对象仍然指向源对象的value
}
}
//写类:必须写无参构造器,一般要求对epuals和hashCode方法重写,
//再者就是重写clone方法




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2