在学习本篇博文前,建议先学习完本人的博文——《详解 继承(上)—— 工具的抽象与分层》

在本人之前的博文中曾讲过“基类”的知识,那么,本篇博文中的主题——Object类 和 基类的知识就密切相关了,那么,我们就直接进入主题吧。

Object类 是JAVA所提供的一个类类型,且是 所有类的基类

因为所有类继承于 Object类,所以,Object类的方法 自然而言就成为 其他类的方法。

而在特殊情况下,子类继承父类时,对于父类的方法的实现过程可能不太满意。

为了处理这种情况,Java也提供了一个机制——覆盖(或者叫做“方法重写”)

一般我们称其为“覆盖”,因为“覆盖”相对而言比较具体形象,而“方法重写” 容易和 本人之前博文中所讲解的 “方法重载”混淆。

下面我们来验证一下上述结论:

由上图可知:我们并没有建立Object类,但是我们却可以调用它的方法,而且它提供了很多方法。

那么,本人在这里来讲解一下有关“覆盖”的 注意事项

注意事项:

  1. 父类中私有方法不能被重写

    因为父类私有方法子类根本就无法继承
  2. 子类重写父类方法时,访问权限不能更低, 最好就一致
  3. 父类静态方法,子类也必须通过静态方法进行重写

我们这篇博文中就主要讲解 Object类 中的 equals()方法toString()方法 的覆盖:

toString()方法 的覆盖:

首先,本人来介绍一下这个方法的用途吧:

用途:

  • 若我们部队这个方法进行重写(覆盖),则返回值为:包名称.类名称@这个对象的首地址
  • 一般我们根据目标对象的类的成员去重写这个方法,以便我们能够得到这个对象的各成员的值

本人用一段代码 和 它的运行结果 来展示一下toString()方法:

还是用我们上一篇博文中的类,来看看这个函数的返回值:

(这里任何类都可以,本人为了缩短读者们的阅读量,所以调用上篇博文的类)

package com.mec.about_override.demo;

public class Demo {

	public static void main(String[] args) {
Animal animal =new Animal("动物");
System.out.println(animal);
} }

由上图可以看出:

而且,在一个类的对象 被输出 或者 转换为 String类型时,JVM自动调用toString()方法。

toString()方法的参数是 “一个类的对象”;

返回值是 “包名称.类名称@这个对象的首地址” 。

现在,本人来编写两个类,并且使其中一个类继承另一个类

在子类中对 toString()方法 进行覆盖:

Animal.java:

package com.mec.about_override.demo;

public class Animal {
private String name; public Animal(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public void cry() {
System.out.println("动物的叫声!");
} }

Dog.java:

package com.mec.about_override.demo;

public class Dog extends Animal {
public Dog(String name) {
super(name);
} public void cry() {
System.out.println("汪汪");
} public void dogAction() {
System.out.println("狗子快跑!");
} @Override
public String toString() {
return "我是" + getName();
} }

Demo.java:

package com.mec.about_override.demo;

public class Demo {

	public static void main(String[] args) {
Dog dog = new Dog("二愣子");
System.out.println(dog);
} }

对比 上图 和 代码改动之前的测试结果,可以清晰地看到,toString()方法 被我们根据我们的用途覆盖了!

equals()方法 的覆盖:

首先,本人先来介绍一下这个方法的主要用途:

用途:

  • 若我们不对这个方法覆盖,调用时将比较两个对象的地址值:

    若相同,则返回true;反之,则返回false
  • 一般我们根据这两个对象的类的成员去重写这个方法,以便比较这两个对象的各成员的值是否相同

那么,本人用一段代码 和 它的运行结果 来展示一下equals()方法:

MecPoint.java:

package com.mec.about_equals.core;

public class MecPoint {	

	private int row;	//private表示这个变量只能在该类中被调用。用于防止外类修改该成员
private int col; public final int MIN_ROW = 1;
public final int MAX_ROW = 25;
public final int DEFAULT_ROW = 12;
public final int MIN_COL = 1;
public final int MAX_COL = 80; //屏幕点坐标范围:共25行、80列
public final int DEFAULT_COL = 40; //默认屏幕点坐标错误时,设为中值 public MecPoint() {
setRow(0);
setCol(0);
} public MecPoint(int x, int y) {
setRow(x);
setCol(y);
} public MecPoint(int x) {
setRow(x);
setCol(0);
} public MecPoint(MecPoint point) {
setRow(point.row);
setCol(point.col);
} public void setPoint(int x, int y) {
setRow(x);
setCol(y);
} public void setPoint(int x) {
setPoint(x, 0);
} public void setPoint(MecPoint source) {
setPoint(source.row, source.col);
} public void setRow(int x) {
if(x <= MIN_ROW || x > MAX_ROW) { //对x范围进行约束
x = DEFAULT_ROW;
}
row = x;
} public int getRow() {
return row;
} public void setCol(int y) {
if(y <= MIN_COL || y > MAX_COL) { //对y范围进行约束
y = DEFAULT_COL;
}
col = y;
} public int getCol() {
return col;
} public void printPoint() {
System.out.println("(" + row + "," + col +")");
} @Override
public String toString() {
return "(" + row + "," + col + ")";
} }

Test.java:

package com.mec.about_equals.core;

public class Test {

	public static void main(String[] args) {
MecPoint pointOne = new MecPoint(3,4);
MecPoint pointTwo = new MecPoint(3,4); System.out.println(pointOne);
System.out.println(pointTwo); System.out.println(pointOne == pointTwo);
} }

现在,我们来看看运行结果:



可以看到的是,最后一句的输出是 false

我们明明给两个对象的成员赋的值是一样的,为什么还是false呢?

这样的结果并不奇怪,因为JAVA对于类对象的 == 比较,是对其首地址的比较,而那两个变量占用的是不同的空间,所以无论如何,结果都是false。

现在就是来介绍 equals()方法 的时候啦,现在,我们来给 Test.java 增加一行代码,看看运行结果:



哦吼,结果还是false,难道我介绍错了吗?

知道本人一贯作风的同学知道,本人现在在“故弄玄虚”。

没错,这个方法并没有错,但是,这个函数是 Object类 提供的,MecPoint类 只是继承这个方法而已,这个方法并不会自动实现对 row 和 col 成员的比较。

本人先来介绍一个关键字——instanceof:

instanceof关键字 ;

(1)左边是一个对象,右边是一个类名称;

(2)这个对象必须是 这个类 或者 这个类的子类;

(若不满足这一点,则编译不通过,无法运行)

(3)若 左边的对象 是 右边的类 或者 这个类的子类,则返回 true,

若 右边的类是 左边的对象的类 或者 这个对象的类的子类,则返回 false。

好了,我们现在来处理一下之前的问题:

我们在MecPoint.java中加入以下代码:

	@Override
public boolean equals(Object obj) {
if(null == obj) {
return false;
}
if(this == obj) {
return true;
}
if(!(obj instanceof MecPoint)) {
return false;
}
MecPoint otherPoint = (MecPoint) obj;
return this.row == otherPoint.row
&& this.col == otherPoint.col;
}



但是,在这里本人还要提出的一点,就是:我们在未来编写代码时,若是想要 覆盖equals()方法,一般都会先覆盖hashcode(),关于这个操作的原因,请观看以下博文:

《覆盖equals时总要覆盖hashCode》

(至于这个知识点,我们可以先不深入了解,但是,养成良好的代码规范,在未来的工作中是很重要的!)

最后,要注意的是:

基类的用 final 修饰的方法,不能再子类中被覆盖。

详解 方法的覆盖 —— toString() 与 equals()的覆盖的更多相关文章

  1. JavaScript类型判断详解(Object.prototype.toString.call()方法进行数据类型的可靠判断)

    前言 在编写一些类库中,我们经常需要判断一些未知的用户的输入和配置,故而需要进行一系列的类型判断.故而总结下JS是如何进行类型判断的 typeof typeof操作符返回一个字符串,表示未经计算的操作 ...

  2. Java基础进阶:继承重点摘要,继承详解,方法重写注意事项,方法重载与重写的区别,抽象类,代码块, 附重难点,代码实现源码,课堂笔记,课后扩展及答案

    继承重点摘要 *继承的特点: 子类在初始化之前,一定要先完成父类数据的初始化 子类在初始化之前,一定要先访问父类构造,完成父类数据的初始化 系统在每一个构造方法中默认隐藏了一句super(); 如果我 ...

  3. 详解 final 和 static

    在我们上一篇博文中提到了 fianl 这个关键字,对于这个关键字,本人在初学时也耗费了极大地心血,甚至和师兄进行了激烈的讨论,并且,在我们讨论.尝试 以及 翻阅各种资料,最终得出了合适.易懂的解释. ...

  4. 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)

    方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...

  5. java多态性方法的重写Overriding和重载Overloading详解

    java多态性方法的重写Overriding和重载Overloading详解 方法的重写Overriding和重载Overloading是Java多态性的不同表现.重写Overriding是父类与子类 ...

  6. Java:集合类的区别详解

    Java中集合类的区别 Array是数组,不在集合框架范畴之内,一旦选定了,它的容量大小就不能改变了,所以通常在编程中不选用数组来存放. 集合 : 集合对象:用于管理其他若干对象的对象 数组:长度不可 ...

  7. Ajax.ActionLink参数详解

    该语法会生成一个a标签,点击a标签会执行一个Ajax请求. 有12个方法重载,下面详解方法中的各项参数: 参数一:linkText string类型 说明:链接显示的文字内容 参数二:actionNa ...

  8. video详解 HTML5中的视频:

    一.video 视频的方法.属性.事件详解 方法:play() 播放  pause() 暂停  属性:currentTime播放到当前的时间   duration视频的总时长 事件:ended 播放完 ...

  9. WebBrowser控件使用详解

    原文:WebBrowser控件使用详解 方法 说明 GoBack 相当于IE的“后退”按钮,使你在当前历史列表中后退一项 GoForward 相当于IE的“前进”按钮,使你在当前历史列表中前进一项 G ...

随机推荐

  1. Linux系统c语言开发环境

    项目 内容 这个作业属于哪个课程 班级地址 这个作业要求在哪里 作业要求地址 学号-姓名 17041506-张政 学习目标 Linux系统下C语言开发环境搭建,学习Linux系统环境C语言开发过程 L ...

  2. iOS自动化环境搭建(超详细)

    1.macOS相关库安装 libimobiledevice > brew install libimobiledevice 使用本机与苹果iOS设备的服务进行通信的库. ideviceinsta ...

  3. jmeter参数化之函数助手(十五)

    jmeter-参数化: 参数化的作用:调用接口入参时.有时要求参数经常变化,如果每次去修改就会变得很繁琐,这时候就需要把经常变化的值改变为提前编辑好的文档或函数中,便于调用时使用不同的值. Jmete ...

  4. 如何测试Linux命令运行时间?

    良许在工作中,写过一个 Shell 脚本,这个脚本可以从 4 个 NTP 服务器轮流获取时间,然后将最可靠的时间设置为系统时间. 因为我们对于时间的要求比较高,需要在短时间内就获取到正确的时间.所以我 ...

  5. HIT软件构造课程3.2总结(Designing Specificaton)

    本节转向“方法/函数/操作”如何定义 上一节是名词 这一节是动词 1.编程语言中的函数和方法 方法 使用者不需要知道方法内部如何实现,这叫做“抽象”. 参数 参数类型是否匹配,在静态检查时完成. 返回 ...

  6. [POJ1190]生日蛋糕<DFS>

    题目链接:http://poj.org/problem?id=1190 题看上去确实很复杂 涉及到半径面积这些,其实看着真的很头疼 但是除去这些就是剪枝优化的dfs算法 #include<cst ...

  7. 【JavaScript】要点知识的个人总结(1)

    米娜桑,哦哈哟~ 该篇章主要基于链接中的参考内容和代码测试得出的结论,面向具有一定基础的前端开发者.如有错误,请指出与包涵. 原型链的解释 https://juejin.im/post/5aa78fe ...

  8. Java并发基础06. 线程范围内共享数据

    假设现在有个公共的变量 data,有不同的线程都可以去操作它,如果在不同的线程对 data 操作完成后再去取这个 data,那么肯定会出现线程间的数据混乱问题,因为 A 线程在取 data 数据前可能 ...

  9. 我是如何从通信转到Java软件开发工程师的?

    我的读者里面有绝大部分都是在校学生,有本科的,也有专科的,我在微信里收到很多读者的提问,大部分问题都跟如何学习编程有关,有换专业自学的.有迷茫不知道如何学习的.有报培训班没啥效果的等等,我能感受到他们 ...

  10. ajax2.0之拖拽上传

    index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> &l ...