脑补一下final

final 用于声明变量/参数/属性、方法和类。

  • 修饰变量:如果变量是基本类型,其值不变;如果是对象,则引用不可再变(内容可变)。
  • 修饰方法:方法不可重写(是否可继承取决于方法的访问修饰符)
  • 修饰类:类不可被继承。


==与equals的区别

我想,大家常规的解释是:==是操作符,比较基本类型,则为其值;比较引用类型,则用以比较两个对象在内存中的哈希地址。 equals是方法,比较的是变量的内容。

---------------

equals是超类Object的方法。参数是一个object对象。本文我将重点借助JAVADOC和源码来阐释。

java.lang.Object里对equals方法的说明:

/**

Indicates whether some other object is "equal to" this one.
The equals method implements an equivalence relation on non-null object references:
  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
Parameters:
obj - the reference object with which to compare.
Returns:
true if this object is the same as the obj argument; false otherwise.
See Also:
hashCode(), java.util.HashMap
*/
public boolean equals(Object obj) {
    return (this == obj);
}

可见equals默认是比较对象的哈希值。

String、Integer这些包装类重写了equals方法。重写的逻辑都是先判断类型是否匹配,然后String是看字符串里每个char字符是否都相同,Integer是两个Integer实例的intValue。

//java.lang.String

/**
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*/
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
} //java.lang.Integer /**
* Compares this object to the specified object. The result is
* {@code true} if and only if the argument is not
* {@code null} and is an {@code Integer} object that
* contains the same {@code int} value as this object.
*/
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}

java.lang.String和java.lang.Integer对equals(Object)方法的定义

BTW,心细的同学可以注意一下java.lang.String中另一个方法equalsIgnoreCase(String anotherString),参数类型不是Object而是String。这一点足见java之美

在做诸如String、Integer包装类型比较时,有的人一律用equals,这样会规避用==带来的比较错误的问题。这没错!不过使用equals也会带来一些隐性的bug,罪魁祸首就是它的参数类型是Object,当equals的两个对象类型不匹配时,编译器是识别不出来的。尤其当我们重构代码时,举个栗子,看下面的语句,如果我将bean的platformCode属性的类型由String改为int,而稍有不慎忘记改这条语句的话,那就出bug了。

if("6".equals(bean.getPlatformCode())

因此,个人认为。。。(此处见解见文末)



比较枚举类型能用==吗?

今天有同学在review代码时,发现如下用==来比较枚举,马上反问这么写没有bug么?是否测试过了?

if (ThirdPayPlatformEnums.TFB == _requestDTO.getThird_pay_platform()) {
_requestDTO.setOrder_no(_requestDTO.getOrder_no().replaceAll("[a-zA-Z]", ""));
}

他让改用equals。

于是,大家都开始思考枚举是不是基本类型,并了解枚举是否可以用==来比较。

经查,答案是肯定的。

java.lang.Enum类对equals的定义是这样的:

public final boolean equals(Object other) {
return this==other;
}

单看这个方法实现,可能认为比较的是哈希地址。

让我们来看看这个equals方法的注解,关注一些关键词:

/**
* Returns true if the specified object is equal to this
* enum constant.
*
* @param other the object to be compared for equality with this object.
* @return true if the specified object is equal to this
* enum constant.
*/

注意到了吧,它将枚举项称为枚举常量。

进一步了解到:在官方文档中也有明确的说明

JLS 8.9 Enums 一个枚举类型除了定义的那些枚举常量外没有其他实例了。 试图明确地说明一种枚举类型是会导致编译期异常。在枚举中final clone方法确保枚举常量从不会被克隆,而且序列化机制会确保从不会因为反序列化而创造复制的实例。枚举类型的反射实例化也是被禁止的。总之,以上内容确保了除了定义的枚举常量之外,没有枚举类型实例。

因为每个枚举常量只有一个实例,所以如果在比较两个参考值,至少有一个涉及到枚举常量时,允许使用“==”代替equals()。

顺便贴出来java.lang.Enum里的clone方法,它保证了枚举的“单例”状态:

/**
* Throws CloneNotSupportedException. This guarantees that enums are never cloned, which is necessary to preserve their "singleton" status.
*
* @return (never returns)
*/
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}

csdn《 比较java枚举成员使用equal还是==》文中分析了分别用==和equals来比较枚举的场景。最终建议是最好用==,也是考虑到了上文中提到的equals的弊端。 同样,如果是数值比较,也最好用基本类型,因为用==来比较数值无争议。



听说,你也一直钟爱着equals。。。的更多相关文章

  1. C# 中的 == 和 equals()有什么区别?

    如以下代码: 1 2 3 4 5 6 7 8 9 int age = 25;   short newAge = 25;   Console.WriteLine(age == newAge);  //t ...

  2. 我的Android进阶之旅------>Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词的功能

    前言 一LRC歌词文件简介 1什么是LRC歌词文件 2LRC歌词文件的格式 LRC歌词文件的标签类型 1标识标签 2时间标签 二解析LRC歌词 1读取出歌词文件 2解析得到的歌词内容 1表示每行歌词内 ...

  3. 别了 oi——一篇高三狗的滚粗遗言

    /* 开始于2015年12月 结束于2016年11月 一年的oi生涯有很多值得怀念的事 还记得去年旺哥找我学oi 当时是一脸的蒙逼 要知道 高二才开始搞是很晚了 然而 也就是那一晚之后 许多事情都变了 ...

  4. js带缩略图的图片切换效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. 南邮ctf-web的writeup

    WEB 签到题 nctf{flag_admiaanaaaaaaaaaaa} ctrl+u或右键查看源代码即可.在CTF比赛中,代码注释.页面隐藏元素.超链接指向的其他页面.HTTP响应头部都可能隐藏f ...

  6. JarvisOJ Basic 爱吃培根的出题人

    听说你也喜欢吃培根?那我们一起来欣赏一段培根的介绍吧: bacoN is one of aMerICa'S sWEethEartS. it's A dARlinG, SuCCulEnt fOoD tH ...

  7. Jarvis OJ平台basic部分wirteup

    Base64? 题目描述: GUYDIMZVGQ2DMN3CGRQTONJXGM3TINLGG42DGMZXGM3TINLGGY4DGNBXGYZTGNLGGY3DGNBWMU3WI=== Base3 ...

  8. 爬虫实战(二) 用Python爬取网易云歌单

    最近,博主喜欢上了听歌,但是又苦于找不到好音乐,于是就打算到网易云的歌单中逛逛 本着 "用技术改变生活" 的想法,于是便想着写一个爬虫爬取网易云的歌单,并按播放量自动进行排序 这篇 ...

  9. Hexo的详细搭建过程——小白的血泪经历QAQ

    Hexo的详细搭建过程 环境要求: node.js git 这里提供Centos8.2下的安装过程: dnf module list nodejs dnf module install nodejs: ...

随机推荐

  1. mysql索引及sql执行顺序

    1, 红黑树 同一层级的黑树到根结点经历的黑树数目一样 最坏情况的时间复杂度 lg n 是二叉树b树 结点可以有多个孩子 b+树 父节点不存储数据聚集索引)的叶子节点会存储数据行,也就是说数据和索引是 ...

  2. ida pro65

    https://elinux.org/CI20_Dev_Zone#Making_a_bootable_SD_card_from_sources IDAPro65.exe: 下载地址:http://pa ...

  3. [DPI] Cisco Application Visibility and Control

    DPI,可分为三部分: https://blogs.cisco.com/enterprise/cisco-traffic-analysis-encrypted-threat-analytics 知名端 ...

  4. 半屏控制器,view: UIViewController+KNSemiModal

    半屏控制器,view:  UIViewController+KNSemiModal https://github.com/kentnguyen/KNSemiModalViewController

  5. activeMQ配置文件

    <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agree ...

  6. java之堆和栈的比较

    当我们第一次接触堆和栈时很多人都不不明白java中为什么要设置这两个概念,他们都有什么作用?堆和栈有什么区别,各自都有什么特点?还有Java中存在栈这样一个后进先出(Last In First Out ...

  7. 洛谷P4570 [BJWC2011]元素 线性基

    正解:线性基+贪心 解题报告: 传送门! 这题其实没什么好写题解的,,,显然贪心一下尽量选魔力大的,不用证明趴挺显然的来着 所以就直接按魔力排个序,插入线性基里面,能插就加个贡献,over 放下代码趴 ...

  8. oracle创建索引表空间

    Oracle 的索引可分为5种,它们包括唯一索引.组合索引.反向键索引.位图索引和基于函数的索引.1.创建索引的标准语法CREATE INDEX 索引名 ON 表名 (列名)TABLESPACE 表空 ...

  9. HBase 的MOB压缩分区策略介绍

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/zNZQhb07Nr/article/details/79832392 HBase应用场景很广泛.社区 ...

  10. 20190316 安装pip的一些问题

    前提条件: 1. windows环境中安装python3.7 2.注意配置环境变量 确认python.和pip都能直接在cmd 控制台使用, 一个是python命令的地址指向,一个是pip命令的地址指 ...