Java 的toString() 和 equals()函数简单介绍
来源:互联网 发布:牛顿迭代法算法 编辑:程序博客网 时间:2024/06/05 18:09
toString() 和 equals() 都是java面试中经常问到的地方.
特别是1条经典问题: equals 和 "==" 的区别...
本文就从简单介绍下这两个object中的函数.
一. toString()函数
我们首先看1个简单的代码例子:
package Object_kng.Object_baseMethod;class Ob_1{}public class Ob_tostring_1{ public static void f(){ Ob_1 a = new Ob_1(); System.out.printf("%s\n", a.toString()); //System.out.printf("%s\n", a); //ok same as below //System.out.println(a); //ok same as below //System.out.printf("%s\n", a.getClass().getName()); //System.out.printf("%s\n", a.getClass().toString()); } }
上面的例子定义了1个空的类 Ob_1. 在下面的启动类中首先实例化类Ob_1 的一个对象. 然后调用了a.toString()函数.
上面代码是能正确编译和执行的.
问题是既然Ob_1是1个空类, 里面并没有定义toString()这个函数, 为何还能调用呢.
1.1 java中所有的类都默认继承基类Object.
原因很简单, 因为Ob_1的toString()方法是继承自类Object的.
Java中所有类都是基类Object的派生子孙类.
如果1个类A在定义中没有指明继承哪个类, 那么类A就继承了类Object!
如果类A extends B呢, 因为B肯定也是Object类的子孙类, 所以无论如何类A肯定是基类Object的派生类or子孙类.
1.2 toString()是类Object内定义的一个方法.
打开jdk api文档, 我们可以查到toString()函数是如下介绍的:
toString
public String toString()
返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:
getClass().getName() + '@' + Integer.toHexString(hashCode())
返回:
该对象的字符串表示形式。
根据上面的的介绍, 我们简单地得出如下的信息:
1. toString()函数返回1个String对象.
2. toString()函数可以被重写, 而且jdk介绍中建议我们为所有类重写这个方法.
3. 不重写这个方法的话, 返回值是 getClass().getName() + '@' + Integer.toHexString(hashCode())
4. toString()不是静态方法, 必须实例化对象才能调用.
1.3 不重写 toString()方法, 其返回值解释
例如上面的代码是没有重写toString()方法的.
执行结果如下:
[java] Object_kng.Object_baseMethod.Ob_1@19c8f4
Object_kng.Object_baseMethod.Ob_1@19c8f45 就是a.toString()的返回值.
根据上面的解析, 我们得知
Object_kng.Object_baseMethod.Ob_1 是由 a.getClass().getName() 来的. 这里实际上是类Ob_1的完整类名(包括所在包名).
而19c8f45 是 Integer.toHexString(a.hashCode()) 获得的.
1.3.1 getClass()方法
这里顺便解析一下getClass(), getClass()方法也是属于基类Object的1个方法, 它返回的是1个对象所属的运行时类.
至于什么是运行时呢, 就是那个对象引用当前状态指向的对象的所属类. 这个跟多态有关.
本人语言表达能力有限, 还是用例子说明的吧:
package Object_kng.Object_baseMethod;class Ob_2{}class Ob_3 extends Ob_2{}public class Ob_getclass_1{public static void f(){Ob_2 a = new Ob_2();System.out.printf("%s\n", a.getClass());a = new Ob_3();System.out.printf("%s\n", a.getClass());}}
本例子有两个空类, 其中Ob_3 继承自 Ob_2
下面首先实力化1个Ob_2 的对象a, 然后输出a.getClass() (实际上输出a.getClass().toString())
然后把引用a 指向 Ob_3 的另1个对象(多态), 然后再输出1次a.getClass().
执行结果:
[java] class Object_kng.Object_baseMethod.Ob_2[java] class Object_kng.Object_baseMethod.Ob_3
可以见到两次输出是不同的, 第一次是Ob_2, 第二次是Ob_3.
也就是说运行时类不是指 引用a是属于哪个类, 而是指a 内存指向的对象属于哪个类, 这个需要多态的知识.
至于getClass().getName()就是获取当前运行时类的完整类名了.
1.3.2 Integer.toHexString(a.hashCode())
那么"@"后面那串字符是什么呢, 实际上它是该对象的hash码的16进制表示.
java中,每1个对象都有1个唯一的hashcode, 它跟这个对象的内存地址有关.
1.4 重写方法的1个简单例子:
package Object_kng.Object_baseMethod;class Point_1{private int x;private int y;public Point_1(int x, int y){this.x = x;this.y = y;}public String toString(){return "[" + x +"," + y +"]" ;}}public class Ob_tostring_2{public static void f(){Point_1 a = new Point_1(2,4);System.out.printf("%s\n", a.toString());System.out.printf("%s\n", a); //ok same as belowSystem.out.println(a); //ok same as below}}
上面定义了1个关于点的类, 有x, y的两个int类型成员(坐标)
然后重写了toString()方法. 不在输出类名和hashcode, 改成输出x和y的值, 并左一定的格式化.
[java] [2,4][java] [2,4][java] [2,4]
1.5 重写方法toString()方法的好处:
1. 方便自定义输出对象的信息.
2. 由上面例子中, System.out.prinft(), 和 System.out.println()里面的参数只放对象名a的话, 实质上会自动调用a.toString().
这样在coding当中就可以利用这两个函数方便调试.
3. 实际上肯定java的自带的类都重写了toString()方法, 例如java.util.Date 日期这个类
1.6 toString()方法的一些小结.
通过上面的例子, 我相信读者最起码清楚如下1点:
toString()是定义在类Object的1个非静态方法.
这意味这个方法必须需要1个已实例化对象才能调用.
也就是为什么我们定义1个整形变量 int x时, 不能利用x.toString()方法把x转化为字符串.
因为x只是1个基本变量, 而不是1个对象啊.
二.equals()函数
2.1 "==" 符号比较的是指向对象的内存地址
下面开始讲另1个函数equals(), 在这之前我们看一下,另1个判断是否相等的符号"=="
接下来又是1个例子:
package Object_kng.Object_baseMethod;class Ob_4{private int id;private String name;public Ob_4(int id, String name){this.id = id;this.name = name;}}public class Ob_equal_1{public static void f(){Ob_4 a = new Ob_4(1,"Kent");Ob_4 a2 = new Ob_4(1,"Kent");System.out.println((a == a2));a2 = a;System.out.println((a == a2));}}
输出结果:
[java] false[java] true
上例子中定义了类Ob_4, 它有两个成员id 和 name.
下面启动类中,实例化了类Ob_4的两个对象a 和 a2, a和a2拥有相同的id和name成员.
但是用 "==" 来比较a 和 a2的话, 它们两者不相等的, 返回了false
接下来执行a2 = a; 这个语句意思就是把引用a2 指向a所指向的对象, 这样的话a2 和 a就指向Heap区的同一块地址了.
再用"==" 比较a 和 a2的话,就返回了true.
由此可见, 用"=="来比较两个对象的话, 实际是比较对象是否hashcode(), 只有两个对象"完全"相同, 才会返回true.
2.2 equals默认比较的是指向对象的内存地址
实际上equals()也是基类Object的一个方法.
public boolean equals(Object obj)
由此可见:
1. 非静态方法, 必须利用已实例化对象调用.
2. 返回boolean类型
3. 需要1个对象(Object)参数, 由于Object是java里所有其他类的超类, 这里也是运用了多态.
4. 冇final关键字, equals方法可以被重写.
我们将上面的代码改一下, 将" == " 改成 equals:
package Object_kng.Object_baseMethod;class Ob_5{private int id;private String name;public Ob_5(int id, String name){this.id = id;this.name = name;}}public class Ob_equals_2{public static void f(){Ob_5 a = new Ob_5(1,"Kent");Ob_5 a2 = new Ob_5(1,"Kent");System.out.println((a.equals(a2)));a2 = a;System.out.println((a.equals(a2)));}}
输出:
[java] false[java] true
见到输出结果跟上面例子是一样的, 所以基类Object的equals方法也是比较内存的地址.
实际上equals()方法在基类Object的源代码如下:
public boolean equals(Objectobj){
return (this == obj)
}
也就是equals调用了 "==", 基本上是等价的.
2.3 equals 和 " == " 并非比较对象的hashCode().
因为hashCode()跟内存地址有关, 所以也有人讲equals 和 "=="比较的是对象的hashCode().
但这种说法是错误的, 因为hashCode()也是基类Object的方法, 也可以重写.
我们来尝试重写hashCode()方法, 来证明观点:
package Object_kng.Object_baseMethod;class Ob_6{private int id;private String name;public Ob_6(int id, String name){this.id = id;this.name = name;}public int hashCode(){return 1;}}public class Ob_equals_3{public static void f(){Ob_6 a = new Ob_6(1,"Kent");Ob_6 a2 = new Ob_6(2,"David");[System.out.println(a);System.out.println(a2);System.out.println((a.equals(a2)));System.out.println((a == a2));a2 = a;System.out.println((a.equals(a2)));System.out.println((a == a2));}}
输出:
[java] Object_kng.Object_baseMethod.Ob_6@1 [java] Object_kng.Object_baseMethod.Ob_6@1 [java] false [java] false [java] true [java] true
上面例子中, 我们在类Ob_6里重写了hashCode的方法, 都返回1.
下面实例化两个对象a 和 a2, 而且两个对象的 id, name成员都不一样.
但是输出对象信息(toString()) 方法, 见到@后面的数字都是1, 也就是它们的hashCode已经相等.
但是后面的比较还是跟之前的例子一样.
也就证明了 equals默认情况下 和 "=="都是比较对象的内存地址, 而非hashCode().
2.4 重写equals()方法.
但是实际生产中, 我需要比较两个不同的对象, 如果两者的所有成员相等, 我们就认为两者相等.这是我们就可以重写equals()方法, 改变它的机制以适用我们的业务需要.
最常见的改写方法:
package Object_kng.Object_baseMethod;class Ob_7{private int id;private String name;public Ob_7(int id, String name){this.id = id;this.name = name;}public boolean equals(Object obj){Ob_7 ob;try{ob = (Ob_7)obj;}catch(ClassCastException e){System.out.printf("warning: the object is not belonged to Class Ob_7!!\n");return false;}catch(Exception e){e.printStackTrace();return false;}if (this.id == ob.id && this.name == ob.name){return true;}return false;}}public class Ob_equals_4{public static void f(){Ob_7 a = new Ob_7(1,"Kent");Ob_7 a2 = new Ob_7(1,"Kent");Ob_7 a3 = new Ob_7(2,"David");System.out.println((a.equals(a2)));System.out.println((a.equals(a3)));System.out.println((a.equals(new Ob_6(1,"kent"))));a2 = a;System.out.println((a.equals(a2)));}}
这个例子在类Ob_7 中重写了equals方法.
注意,重写这个方法涉及了多态的知识, 必须将形参强制转化为对应的类, 才可以比较成员.
为防止传错了其他类的对象的异常, 最好加上try{}语句来捕捉.
输出结果:
符合我们的需要了, 只要id和name相等, 我们就认为这两个对象相等:
[java] hello ant, it's the my meeting with ant! [java] true [java] false [java] warning: the object is not belonged to Class Ob_7!! [java] false [java] true
2.5 Java里有一些自带的类也重写了equals()方法.
最明显的例子就是String类. 下面例子:
package Object_kng.Object_baseMethod;public class Ob_equals_5{public static void f(){String s1 = "abc";String s2 = new String("abc");System.out.println((s1.equals(s2)));System.out.println((s1 == s2));}}
输出:
[java] true [java] false
上面定义了两个字符串对象, 值都是"abc"
用equals比较两者是相等的.
用 "==" 则不等.
由此可见String类改写了equals方法, 当然更可能是String的其中1个超类改写了equals方法.
2.5 Java里equals 和 "==" 的区别
以后大家可以这样回答面试官:
1. "==" 可以比较基本类型(如 int 和 boolean)或对象.
2. equals是对象的非静态方法, 只能用于比较对象, 不能比较基本类型.
3. "==" 用于对象时, 比较的是对象内存地址, equals() 通常情况下也是会比较内存地址.
4. 一些类如String() 改写了equals()方法, 比较的是String对象的值, 而不是内存地址.
5. 我们可以改写equals()方法, 根据需要来比较两个对象.
- Java 的toString() 和 equals()函数简单介绍
- Java equals和toString用法
- equals函数,hashCode(),toString()的作用和实现方法
- Java记录 -57- Object的equals、hashcode和toString方法
- java equals() 和toString()方法重写
- JAVA学习--toString和equals用法
- Java中equals()方法和toString()方法
- [ Java学习 ] toString方法 和 equals方法
- equals&&hashCode&&toString函数
- JAVA基础学习(八)---多态、简单工厂、Object类equals和toString
- Java toString equals hashCode 方法的重写
- Java equals() ,hashCode(),toString() 的推荐写法。
- equals()和toString()方法的使用
- Object的equals方法和toString方法
- Object类的toString()和equals()方法
- java--equals toString
- get和set,有参无参构造函数,toString,equals和hashCode的MyEclipse快捷键
- 黑马程序员:Object类和equals、toString方法介绍
- Oracle SQL的优化
- 一种经历,一种体会。
- oracle中DDL DML指什么?
- 你对position的了解有多少
- mysql insert 乱码
- Java 的toString() 和 equals()函数简单介绍
- mapreduce的简单应用
- 从来不是别人的不幸和痛苦
- hadoop执行job时,如何解决map /reduce程序执行时卡住现象
- Hdu 2224 The shortest path(双调TSP)
- Delta3D中 dtActors中常用actor 分析
- Underscore.js笔记
- [ javascript ] 小东西!
- ORACLE扩展表空间