java的Object类的方法
导读:文章内容选自尚硅谷,JDK8,采用eclipse开发环境,主要介绍Object类中最常用的两种方法:equals和toString方法。
Object类的特性
- Object类没有属性
- Object类只有一个空参的构造器
关于Object类的方法,如下图
其中的部分方法是有返回值的,比如说getClass()
package com.atguigu.java;
public class ObjectTest {
public static void main(String[] args) {
Order order = new Order();
System.out.println(order.getClass());
System.out.println(order.getClass().getSuperclass());
}
}
class Order{
}
运行结果为
class com.atguigu.java.Order
class java.lang.Object
equals(Object obj)
equals(Object obj) 是Object类中最常用的方法之一。
比较 运算符== 与 equals() 的区别
运算符== 的运用(针对基本数据类型)
- 运算符== 两边的对象可以是基本数据类型,也可以是引用数据类型
- 运算符== 基本数据类型 比较的是左右两边变量的值的大小
- 运算符== 引用数据类别 比较的是左右两边变量所存放的地址值是否相等
- 运算符== 使用时,必须保证左右两边变量类型一致(包括了自动类型提升情况),否则编译器报错
比较基本数据类型的值如下
package com.atguigu.java;
public class EqualsTest {
public static void main(String[] args) {
int i = 10;
int j = 10;
System.out.println(i == j);
double c = 10.0;
System.out.println(i == c);//自动类型提升
char c1 = 10;
System.out.println(i == c1);
char c2 = 65;
char c3 = 'A';
System.out.println(c2 == c3);
// boolean b = true;
// System.out.println(b == i); //基本数据类型中,不能把boolean和其他类型进行比较,编译器会报错
}
}
运行结果为
true
true
true
true
ps:基本数据类型中,不能把boolean和其他类型进行比较,编译器会报错,但是布尔型和布尔型之间可以用运算符== 进行比较。
运算符== 的运用(针对引用数据类型)
先创建一个Customer对象
package com.atguigu.java;
public class Customer {
private String name;
private int age;
}
点击Alt+shift+s,打开工具栏中的Source项
点击Generate Getters and Setters,创建了调用私有属性的公用方法,再点击Generate Constructor Using Fields,构造一个空参构造器和带参数的构造器,创建结果如下
package com.atguigu.java;
public class Customer {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Customer(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Customer() {
super();
}
}
再在EqualsTest中进行测试
Customer cust1 = new Customer("Tom",21);
Customer cust2 = new Customer("Tom",21);
String str1 = new String("atguigu");
String str2 = new String("atguigu");
System.out.println(cust1 == cust2);
System.out.println(str1 == str2);
运行结果都为false,因为运算符==此时比较的是两个栈空间变量的地址值是否相等,这儿new了两个cust对象,指向堆空间的不同地址,故肯定是不相等的。
ps:字符串是引用数据类型的,这儿的str1和str2也是存放的指向字符串常量池的两个地址,故为false。
equals方法的运用
equals方法是对象的方法,在运用之前要先创建一个对象,才能调用方法。而且一般要在子类中重写equals方法。
- equals()方法仅适用于引用数据类型
- 如果没有在子类中对equals方法进行重写,equals方法等于用运算符==。
- 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是 两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
在EqualsTest类中进行测试,代码如下
System.out.println(cust1.equals(cust2));
System.out.println(str1.equals(str2));
Date date1 = new Date(6441316161L);
Date date2 = new Date(6441316161L);
System.out.println(date1.equals(date2));
运行结果为
false
true
true
这儿之所以第一个运行结果是false,是因为我们没有在Customer类中重写equals方法,而调用的是Object类中的equals方法,Object类中的equal方法定义为
public boolean equals(Object obj){
return (this == obj);
}
可见,调用Object类中的equals方法等同于运算符==,结果肯定为false
ps:在运行
System.out.println(cust1.equals(cust2));
这儿是一个多态性的应用,因为equals方法定义的形参为Object类型的,这儿我们传入的是Object类的子类,只不过没有重写过equals方法。
运行 System.out.println(str1.equals(str2)); 返回true,是因为我们在字符串类中重写了equals方法,调用的是子类的方法,进行对实体内容而不是地址值的比较。
运行System.out.println(date1.equals(date2)); 返回true同理,不过我们这儿没有自定义一个Date类,需要从java标准库中进行导入,这儿有一个快捷键
ctrl+shift+o
导入java.util.Date
通常情况下用equals方法是要对实体内容进行比较,因此不能用Object的equals方法,必须在子类中重写一个equals方法,这儿我们在Customer对象中重写一个equals方法
代码如下
@Override
public boolean equals(Object obj) {
if(this == obj){
return true;
}
if(obj instanceof Customer){
Customer cust = (Customer)obj;
return cust.age == this.age && this.name.equals(cust.name);
}else{
return false;
}
}
运行System.out.println(cust1.equals(cust2)); 其结果为true。
ps:手动重写毕竟过于麻烦,在eclipse环境中,点击工具栏中的source或者按Alt+shift+s,在点击Generate harsCode() and equals(),会自动重写一个equals()和hashCode()方法,这儿我们只要equals()就好,代码如下:
// @Override
// public int hashCode() {
// final int prime = 31;
// int result = 1;
// result = prime * result + age;
// result = prime * result + ((name == null) ? 0 : name.hashCode());
// return result;
// }
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
ps:自动重写的方法相比于手动重写的方法,其代码的健壮性要好,它遵循equals方法的原则
图片来源自尚硅谷课件PPT
toString()方法的使用
先付上代码,创建一个ToStringTest类
package com.atguigu.java;
public class ToStringTest {
public static void main(String[] args) {
Customer cust1 = new Customer("Tom",21);
System.out.println(cust1);
System.out.println(cust1.toString());
}
}
发现运行结果都为由哈希表算出的虚拟地址值。
com.atguigu.java.Customer@15db9742
com.atguigu.java.Customer@15db9742
说明在执行 System.out.println(cust1.toString()); 的时候,而点击toString方法查看其源代码
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
而在调用System.out.println(cust1); 的时候,参数列表里是对象的引用,这儿是println重载方法的一种,点进println的时候
public void println(Object x) {
String s = String.valueOf(x);
synchronized (this) {
print(s);
newLine();
}
}
然后再点valueOf查看源码
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
发现最后还是调用了toString(),因为我们此时没有重写toString,这儿的toString是Object类中的方法。
与equals方法类似,像String、Date、File、包装类等都重写了Object类中的toString()方法。重写以后,输出的一般为对象的实体内容而非地址值。在ToStringTest类中加入后续代码
String str = new String("mm");
System.out.println(str);
Date date = new Date(3565112656L);
System.out.println(date);
运行结果为
mm
Wed Feb 11 14:18:32 CST 1970
输出的是 实体内容 而非地址值,因此像String类型和Date类型,其实是重写了toString方法的。与equals重写类似,在eclipse环境中同样支持自动重写功能。
假如说我们要在Customer类中重写toString方法,仅需在Customer类中打开工具栏中的source或者点击快捷键,再点击Generate toString,最后点击Customer类中的两个属性,就会自动生成打印类中属性的toString方法。(也可以点击Customer类中的方法,会自动生成打印类中方法的toString方法)
@Override
public String toString() {
return "Customer [name=" + name + ", age=" + age + "]";
}
此时再次运行
System.out.println(cust1);
System.out.println(cust1.toString());
其结果为
Customer [name=Tom, age=21]
Customer [name=Tom, age=21]
即可打印出实体内容中的属性值。