目录
Java中的Object
类介绍及常用方法和经典接口
Object
类介绍
Object
类是Java中所有类的父类,位于Java.lang
包中,默认创建的所有对象都继承自Object
类
Object
类常用方法
toString()
方法
默认情况下,如果直接打印对象名(等于调用对象名.toString()
),则打印出的内容是对象的包名+类名+地址,例如下面的代码:
public class Person {
private String name = "zhangsan";
private int age = 16;
}
// 测试
public class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person);
System.out.println(person.toString());
}
}
输出结果:
com.epsda.advanced.test_Object.Person@154617c
com.epsda.advanced.test_Object.Person@154617c
如果看toString()
方法的源码可以发现toString()
实际实现的方式:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
为了打印的是对象的内容而不是对象的地址,需要重写toString()
方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
有了重写的toString()
方法,直接打印对象名或者调用toString()
方法就可以直接打印对象中的内容
public class Person {
private String name = "zhangsan";
private int age = 16;
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
// 测试
public class Test {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person);
System.out.println(person.toString());
}
}
输出结果:
Person{name='zhangsan', age=16}
Person{name='zhangsan', age=16}
equals()
方法
默认情况下,如果使用==
比较基本数据类型,比较的是对应变量中的值,如果使用==
比较引用数据类型,则比较的是对应的地址值,此时如果需要比较引用数据类型中的内容,就需要使用equals()
方法。但是如果是自定义的类类型,没有重写equals()
方法时,比较的结果依旧与==
相同
public class Test {
public static void main(String[] args) {
Person person1 = new Person();
Person person2 = new Person();
System.out.println(person1 == person2);
System.out.println(person1.equals(person2));
}
}
输出结果:
false
false
之所以出现这个情况,是因为在自定义的类类型没有重写equals
时会默认调用父类Object中的equals
,该equals
方法比较方式依旧是按照地址比较
public boolean equals(Object obj) {
return (this == obj);
}
所以为了不按照地址比较,需要在自定义的类类型中重写equals
方法
需要注意,一般情况下,建议是重写equals方法的同时也需要重写hashCode()
方法,这是为了保持对象一致性,并且确保数据结构(如哈希表实现的集合类HashMap
、HashSet
等)能够正确地工作。下面以仅重写equals
方法为例
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
此时再进行比较时,使用equals
方法就会调用重写的equals
方法,从而比较的是对象中的内容
public class Test {
public static void main(String[] args) {
Person person1 = new Person();
Person person2 = new Person();
System.out.println(person1 == person2);
System.out.println(person1.equals(person2));
}
}
输出结果:
false
true
clone()
方法
如果想根据一个已经存在的对象创建一个成员相同的同类型对象(彼此地址不同),则可以使用clone()
方法,使用clone
方法前先在对应的类中重写clone
方法,因为父类中的clone
方法属于protected
修饰的方法,在main
方法直接访问是访问不到的
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone(); // 调用父类的clone()方法
}
// 测试
public class Test {
public static void main(String[] args) {
Person person = new Person("张三", 20);
try {
Person person1 = (Person) person.clone();
} catch (CloneNotSupportedException e) {
System.out.println("无法克隆");
}
}
}
经典接口
Comparable
接口
在Java中基本数据类型的数据(除boolean
类型外)需要比较大小的话,之间使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。
Java给所有引用数据类型的大小比较,指定了一个标准接口,就是java.lang.Comparable
接口:
package java.lang;
public interface Comparable{
int compareTo(Object obj);
}
使用步骤如下:
第一步:哪个类的对象要比较大小,哪个类就实现java.lang.Comparable
接口,并重写方法,方法体就是要如何比较当前对象和指定的另一个对象的大小
第二步:对象比较大小时,通过对象调用compareTo
方法,根据方法的返回值决定谁大谁小。
this
对象(调用compareTo
方法的对象)减指定对象(传入compareTo()
的参数对象)大于0,返回正整数this
对象(调用compareTo
方法的对象)减指定对象(传入compareTo()
的参数对象)小于0,返回负整数this
对象(调用compareTo
方法的对象)减指定对象(传入compareTo()
的参数对象)等于0,返回零
代码示例:
实现了Comparable
接口的Student
类
public class Student implements Comparable{
private String name;
private int score;
public Student() {
}
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
/*
this:代表students[i]
o:代表students[i+1]
如果students[i].getScore()-students[i+1].getScore()>0
证明数组中的前面一个对象比后面一个对象的分数高
*/
@Override
public int compareTo(Object o) {
Student s = (Student) o;
return this.getScore()- s.getScore();
}
}
测试代码如下:
public class Test01 {
public static void main(String[] args) {
//创建一个数组
Student[] students = new Student[3];
Student s1 = new Student("张三", 100);
Student s2 = new Student("李四", 60);
Student s3 = new Student("王五", 80);
students[0] = s1;
students[1] = s2;
students[2] = s3;
for (int j = 0; j<students.length-1;j++){
for (int i = 0;i<students.length-1-j;i++){
//如果students[i]比students[i+1]大,就排序换位置
if (students[i].compareTo(students[i+1])>0){
Student temp = students[i];
students[i] = students[i+1];
students[i+1] = temp;
}
}
}
//遍历
for (int i = 0; i < students.length; i++) {
System.out.println(students[i]);
}
}
}
输出结果如下:
Student{name='李四', score=60}
Student{name='王五', score=80}
Student{name='张三', score=100}
Comparator
接口
当一个类无法被随意修改时,就没有办法再添加其他内容,但是该类又没有实现前面的Comparable接口,此时就需要使用Comparator接口(java.util.Comparator
)自定义比较方式
package java.util;
public interface Comparator{
int compare (Object o1,Object o2);
}
那么我们想要比较某个类的两个对象的大小,怎么做呢?步骤:
第一步:编写一个类,我们称之为比较器类型,实现java.util.Comparator
接口,并重写方法
- 方法体就是你要如何指定的两个对象的大小
第二步:比较大小时,通过比较器类型的对象调用compare()
方法,将要比较大小的两个对象作为compare
方法的实参传入,根据方法的返回值决定谁大谁小。
o1
对象减o2
大于0返回正整数o1
对象减o2
小于0返回负整数o1
对象减o2
等于0返回零
例如
- 固定不变的
Person
代码:
// Person固定假设不能修改增加Comparable接口以及Comparator接口
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
}
自定义新的类实现Comparator
接口
// 自定义类实现Comparator类
public class ToCmp implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Person p1 = (Person) o1;
Person p2 = (Person) o2;
// 年龄升序
return p1.getAge() - p2.getAge();
}
}
测试代码:
// 测试
public class Test {
public static void main(String[] args) {
//创建一个数组
Person[] persons = new Person[3];
Person p1 = new Person("张三", 100);
Person p2 = new Person("李四", 60);
Person p3 = new Person("王五", 80);
persons[0] = p1;
persons[1] = p2;
persons[2] = p3;
// 使用冒泡排序为例
for (int j = 0; j<persons.length-1;j++){
for (int i = 0;i<persons.length-1-j;i++){
//如果Persons[i]比Persons[i+1]大,就排序换位置
if (new ToCmp().compare(persons[i],persons[i+1])>0){
Person temp = persons[i];
persons[i] = persons[i+1];
persons[i+1] = temp;
}
}
}
//遍历
for (int i = 0; i < persons.length; i++) {
System.out.println(persons[i]);
}
}
}
输出结果:
Person{name='李四', age=60}
Person{name='王五', age=80}
Person{name='张三', age=100}