当前位置: 首页 > wzjs >正文

石家庄做网站裕华区十大接单推广平台

石家庄做网站裕华区,十大接单推广平台,淘宝网站c 设计怎么做,wordpress轻博客模板注!!! 本文章所使用的编写代码和示例软件为: IntelliJ IDEA Community Edition 2021.3.2 本文学习目标: 知道什么是Object 类。知道Object 类的 equals 方法和 hashCode 方法,以及怎么去用。知道 Compar…

注!!!

本文章所使用的编写代码和示例软件为:

IntelliJ IDEA Community Edition 2021.3.2

本文学习目标:

  1. 知道什么是Object 类。
  2. 知道Object 类的 equals 方法和 hashCode 方法,以及怎么去用。
  3. 知道 Comparable接口和 Comparator接口,以及怎么去使用。

1. Object 类

1.1 什么是 Object 类

Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的。默认会继承Object 父类,简单来说:Object 类是所有类的父类,即所有类的对象都可以使用Object的引用进行接收。

举个例子:使用Object 接收所有类的对象

class Person {}class Student {}
public class Test {public static void main(String[] args) {Person person = new Person();Student student = new Student();func(person);func(student);}public static void func(Object obj) {System.out.println(obj);}
}

 //运行结果

Demo1.Person@41629346
Demo1.Student@404b9385

 1.2 Object 类提供的方法

Object 类提供了一些定义好的方法,接下来介绍两个:equals() 方法,hashCode() 方法。

1.2.1 对象比较 equals 方法

在Java中,使用 == 进行比较时:

a. 如果 == 左右两边是基本类型变量,则比较的是变量中的值是否相同。

b. 如果 == 左右两边是引用类型变量,则比较的是引用变量地址是否相同。

c. 如果要比较对象中内容,必须重写Object中的equals 方法,因为equals 方法默认也是按照地址比较的

// Object类中的equals方法
public boolean equals(Object obj) {return (this == obj);   // 使用引用中的地址直接来进行比较
}

 我们可以写个代码来证明:

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}
}public class Test {public static void main(String[] args) {Person person1 = new Person("小明",12);Person person2 = new Person("小明",12);System.out.println(person1 == person2);System.out.println(person1.equals(person2));}
}

//运行结果

false
false

 Person 类重写 equals 方法后重新比较

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}public boolean equals(Object obj) {if(obj == null) {return false;}if(this == obj) {return true;}//检测是不是Person类对象if (!(obj instanceof Person)) {return false ;}Person person = (Person) obj;  // 向下转型 比较属性值return this.name.equals(person.name) && this.age == person.age;}
}public class Test {public static void main(String[] args) {Person person1 = new Person("小明",12);Person person2 = new Person("小明",12);System.out.println(person1 == person2);System.out.println(person1.equals(person2));}
}

//运行结果

false
true

结论: 比较对象中内容是否相同时,一定要重写equals 方法。

1.2.2 hashCode 方法

 hashCode 方法的功能简单来说就是帮忙算一个具体的对象地址

hashCode方法的源码

public native int hashCode();

显然,这是一个native 方法,底层是由C/C++代码写的,我们看不见。

我们认为两个名字,年龄相同的对象,将储存在同一个位置,逻辑上是这样的,但实际上不是。

如果不重写hashCode()方法,我们可以来看示例代码:

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}
}public class Test {public static void main(String[] args) {Person person1 = new Person("小明",12);Person person2 = new Person("小明",12);System.out.println(person1.hashCode());System.out.println(person2.hashCode());}
}

//运行结果

990368553
1096979270

我们发现:两个对象的hash值不一样,但两个对象的名字、年龄是一样,这结果与我们期望的不符。

像重写 equals 方法,我们也可以重写 hashCode 方法。

class Person {public String name;public int age;public Person(String name, int age) {this.name = name;this.age = age;}public int hashCode() {return Objects.hash(name,age);}
}public class Test {public static void main(String[] args) {Person person1 = new Person("小明",12);Person person2 = new Person("小明",12);System.out.println(person1.hashCode());System.out.println(person2.hashCode());}
}

//运行结果

23458766
23458766

 我们发现:哈希值一样。

总结:

  1. hashcode方法用来确定对象在内存中存储的位置是否相同。
  2. 事实上hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的 散列码,进而确定该对象在散列表中的位置。

 2. 接口使用实例

给对象数组排序(不灵活)

现在我们创建一个学生类,并且实例化两个学生对象如下:

public class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class Test {public static void main(String[] args) {Student student1 = new Student("小明",12);Student student2 = new Student("小红",13);}}

现在我们打算比较两个对象,

public class Test {public static void main(String[] args) {Student student1 = new Student("小明",12);Student student2 = new Student("小红",13); System.out.println(student1 <student2);}}

显然这种写法是错误的,student1与student2是两个引用变量,它们存的是对象的地址,不能直接进行比较,从这里我们也得到两个疑问:

  1.  当前自定义类,要根据什么样的规则进行比较?
  2. 这个规则如何定义?

这里我们可以用到Java提供的 Comparable 接口,定义一个规则,以便去实现比较。

Comparable 本身就有“比较”的意思,这个接口因此也是用于比较的。

我们进入到 Comparable 接口,可以看到

这里的 Comparable<T> 中的 T 指的是 泛型参数,就是你要比较哪个类就写哪个类,这里我们要比较两个学生对象,就写 Student 类, 接着它里面有一个抽象方法 compareTo() ,这个就是比较的规则,我们可以在子类中重写需要的规则。

我们使Student 类实现这个接口,如下:

public class Student implements Comparable<Student> {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {if(this.age > o.age) {return 1;} else if(this.age == o.age) {return 0;} else {return -1;}}
}

注意,这里的 this 指的是 谁调用这个方法就是谁

这里是按年龄进行比较,这下子我们就能比较了,我们设想输出结果为 -1

public class Test {public static void main(String[] args) {Student student1 = new Student("小明",12);Student student2 = new Student("小红",13);System.out.println(student1.compareTo(student2));}}

//运行结果

-1

student1 小于 student2,因此输出-1,这与我们设想的一样。 

 那么我们如果想按照名字首字母比较,又该怎么样呢?首先,我们明确一件事,名字的数据类型为 String 是引用数据类型,它是一个类,既然是类那么它也会有很多方法

在它的目录底下,我们发现了 compareTo()方法 ,因此根据名字首字母进行比较我们可以这样写

public class Student implements Comparable<Student> {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {return this.name.compareTo(o.name);}
}

//这里调用的是 String 类的compareTo()方法。

既然两个对象我们已经知道如何去比较了,那么多个对象呢?对于多个对象,我们不得不想到数组,Student类 也是一个类型,那么可以创建一个 Studnet数组把多个 Student对象存起来。

public class Test {public static void main(String[] args) {Student student1 = new Student("李明",12);Student student2 = new Student("小红",9);Student student3 = new Student("王刚",11);Student[] stu = {student1,student2,student3};}
}

当初我们在学习数组排序时,曾使用过 Arrays 类的 sort()方法,只不过那会数组的类型是基本数据类型,那么现在是引用数据类型,还能行吗?我们试试

public class Test {public static void main(String[] args) {Student student1 = new Student("李明",12);Student student2 = new Student("小红",9);Student student3 = new Student("王刚",11);Student[] stu = {student1,student2,student3};System.out.println("排序前:" + Arrays.toString(stu));Arrays.sort(stu);System.out.println("排序后:" + Arrays.toString(stu));}
}

//运行结果

排序前:[Student{name='李明', age=12}, Student{name='小红', age=9}, Student{name='王刚', age=11}]
排序后:[Student{name='小红', age=9}, Student{name='王刚', age=11}, Student{name='李明', age=12}]

显然是可以进行排序的,并且是按照年龄升序进行排序的,这是为什么呢?

 这里需要明白一件事,就是sort()方法排序自定义类数组时会依赖 Comparable 接口,比较前,sort()方法会检测自定义类是否实现了 Comparable 类,如果没有实现就会报错,如果实现了,则会通过 Comparable 接口中的 compareTo()方法进行排序,而 compareTo方法我们在Student 类中已经重写了,就是按年龄进行排序。当一个类实现了 Comparable 接口,就意味着这个类的对象之间有了自然的比较方法。

写到这,我们的两个疑问基本解决了,但是我们有发现一个问题:当根据不同的属性进行比较时,不得不对 Student 类中重写的 compareTo()方法进行修改,这是很不方便的,那么有没有更方便的方法呢? 其实是有的,就是换一个接口

给对象数组排序(灵活)

我们可以通过 Comparator 接口实现,简单讲就是设置一个比较器,让 sort()方法按照这个比较器去实现排序

我们先定义一个学生类

public class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

再定义一个类,作为比较器,我们姑且设置它为“按年龄升序排序”比较器。这个类需要实现 Comparator 接口,并且重写 compare()方法。

public class AgeRise implements Comparator<Student> {@Override
//这里如果o1大于o2,则返回一个正数,否则返回一个负数。public int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge();}
}

接着创建一个测试类,创建一个学生类数组,并且放入三个对象,创建一个比较器对象,接着把比较器对象作为 sort()方法的第二个参数,那么sort()方法再对数组进行排序时,就会按照比较器的规则进行排序。

public class Test {public static void main(String[] args) {Student student1 = new Student("黎明",12);Student student2 = new Student("王昂",14);Student student3 = new Student("李白",9);AgeRise ageRise = new AgeRise();Student[] stu = {student1,student2,student3};System.out.println("排序前:" + Arrays.toString(stu));Arrays.sort(stu,ageRise);System.out.println("排序后:" + Arrays.toString(stu));}
}

//运行结果

排序前:[Student{name='黎明', age=12}, Student{name='王昂', age=14}, Student{name='李白', age=9}]
排序后:[Student{name='李白', age=9}, Student{name='黎明', age=12}, Student{name='王昂', age=14}]

注意: 被比较的类可以不实现 Comparator 接口。

我们发现 sort()方法确实是按照比较器的规则进行比较了,那么我们想让它按名字排序,再定义一个比较器

public class NameCompare implements Comparator<Student> {@Overridepublic int compare(Student o1, Student o2) {return o1.getName().compareTo(o2.getName());}
}

在测试类中运行一下

public class Test {public static void main(String[] args) {Student student1 = new Student("黎明",12);Student student2 = new Student("王昂",14);Student student3 = new Student("李白",9);NameCompare nameCompare = new NameCompare();Student[] stu = {student1,student2,student3};System.out.println("排序前:" + Arrays.toString(stu));Arrays.sort(stu,nameCompare);System.out.println("排序后:" + Arrays.toString(stu));}
}

 //运行结果

排序前:[Student{name='黎明', age=12}, Student{name='王昂', age=14}, Student{name='李白', age=9}]
排序后:[Student{name='李白', age=9}, Student{name='王昂', age=14}, Student{name='黎明', age=12}]

可以看到,确实是按照名字进行排序了。

总结: 从上述两个例子,我们可以知道使用 Comparator 接口可以实现灵活的排序规则,我们不必每次都去比较的类中修改,只要定义我们需要的比较器即可,这样子就实现了解耦。

到此,“抽象类和接口”的内容已完结,若本文有不对的地方还请指出,多谢!!!

http://www.dtcms.com/wzjs/347667.html

相关文章:

  • 苏州网站建设哪里好税收大数据
  • 中国建设网网站打开百度官网
  • 哪个网站做兼职猎头seowhy论坛
  • 公众号怎么做网站编程培训班学费一般多少钱
  • 做国外夏令营的网站网络优化工具app手机版
  • WordPress限制文件夹文件数seo 优化思路
  • wordpress发布文章提示更新失败aso优化报价
  • 怎么做重庆时时彩网站代理简单的网页设计作品
  • 合肥做推拉棚网站推广搜索引擎seo推广
  • 郑州主动营销网站邵阳seo优化
  • 做个 公司网站多少钱哪里有免费的网站推广服务
  • windows 2012做网站伪静态网站营销推广
  • 电商网站功能模块图最新国际新闻事件
  • 上海做网站品牌公司西安互联网推广公司
  • 网站建设策划案模板网络运营是什么意思
  • 用rp怎么做网站按钮下拉框青岛seo排名扣费
  • 做网站交互百度指数
  • 怎样做网站seo搜索引擎的优化方法
  • 温州网站建设方案案例设计网址模板建站
  • 网站建设需要什么硬件郑州seo顾问培训
  • 做youtube视频网站惠州seo快速排名
  • 合肥的房产网站建设惠州seo外包
  • 网站自助建设平台百度免费安装下载
  • 沈阳网站建设公司的公司个人免费建站软件
  • php动态网站开发案例答案第二章北京seo关键词优化外包
  • 宁波网站定制服务百度链接提交收录入口
  • 如何测试 网站seoul怎么读
  • 官方网站建设 磐石网络多少费用如何增加网站的外链
  • 做公司 网站建设百度一下首页
  • 微网站自助建设产品推广运营的公司