Lint 错误:可疑的相等检查:在 Object DiffUtilEquals 中未实现 equals()

Posted

技术标签:

【中文标题】Lint 错误:可疑的相等检查:在 Object DiffUtilEquals 中未实现 equals()【英文标题】:Lint Error: Suspicious equality check: equals() is not implemented in Object DiffUtilEquals 【发布时间】:2019-09-17 14:32:19 【问题描述】:

android Studio/Gradle 3.4 似乎引入了一个新的 lint 错误DiffUtilEquals。它由DiffUtil<Any> 触发,然后在areContentsTheSame 函数中作为备用oldItem == newItem 调用。 linter 抛出的错误是

Suspicious equality check: equals() is not implemented in Object

示例代码:

 override fun areContentsTheSame(oldItem: Any, newItem: Any): Boolean 
        return when 
            oldItem is MyKotlinClass && newItem is MyKotlinClass -> true
            oldItem is MyKotlinClass2 && newItem is MyKotlinClass2 -> oldItem.title == newItem.title
            else -> oldItem == newItem // Lint error on this line
        
    

这种 when 语句在 DiffUtil 中非常常见,用于具有多种类型的适配器,您可以根据它们的类比较每种类型。

处理此错误的最佳方法是什么?是否应该将<Any> 更改为类似于Equatable 的某个接口,或者适配器中使用的所有类都应该实现一些包含比较方法的接口?

【问题讨论】:

“对于具有多种类型的适配器,此代码在 DiffUtil 中非常常见”——when 中的第一种情况似乎很奇怪。内容是一样的……纯粹基于它们是什么 Kotlin 类? 只是一个人为的例子,你说得对,它可能不会发生在现实世界中,但我想保持这个例子简单 您究竟是从哪里获得的课程? embedded DiffUtil 接受areContentsTheSame 中的整数,并且没有泛型类型。 这个,developer.android.com/reference/androidx/recyclerview/widget/… 将数据关键字添加到您的班级。例如数据类模型 【参考方案1】:

所有java.lang.Objects 都有一个equals() 函数。它是语言基础的一部分。然而,并不是所有的都覆盖它,这就是 linter 触发的原因。 (SomeClass() as Any).equals(SomeClass()) 可以很好地编译实例(当然,假设您有一个名为 SomeClass 的类)。

我无法用任何类来重现这一点 - 它必须是你提到的那个 (DiffUtil.ItemCallback)。我扩大了检查,上面写着:

可疑的相等检查:在 Object 中没有实现 equals()

DiffUtil 使用检查信息:areContentsTheSame 来生成差异。如果方法实现不正确,例如使用标识 equals 而不是 equals,或者在尚未实现它的类上调用 equals,可能会出现奇怪的视觉伪影。

这个答案最好用不同的 sn-p 来证明:

data class One(val t: String)

val x = object : DiffUtil.ItemCallback<One>() 
    override fun areItemsTheSame(p0: One, p1: One): Boolean  TODO() 
    override fun areContentsTheSame(p0: One, p1: One): Boolean 
        return p0 == p1
    


这将编译。如果您不知道,data class 会生成自定义的equals 方法。如果您在 Android Studio 中删除 data 关键字,错误将再次出现,因为没有覆盖 equals 方法。

TL;DR: 检查抱怨缺少自定义的equals 方法,和/或使用identity checking(Java 中的== 或Kotlin 中的===) .但是,=== 会发出一条单独的消息,这会更容易确定解决方案:

可疑的相等性检查:您的意思是 == 而不是 ===

我认为 Java 中的 == 会引发类似的信息,但建议使用 equals 作为替代。 我没有验证这个

至于解决方案:

如果你知道自己在做什么(不推荐)

您可以抑制或更改严重性以远离错误。更改严重性或全局抑制在同一个地方。文件 -> 设置 -> 编辑器 -> 检查 > Android -> Lint -> 正确性 -> 可疑的 DiffUtil 相等性

或者你可以在本地抑制它:

@SuppressLint("DiffUtilEquals")

如果您想安全行事

不幸的是,这更复杂。

Any 没有保证 equals 被覆盖 - 因此检查。您真正拥有的唯一可行选择是使用不同的类。并且使用Equatable 也不是一个坏主意。但是,与 Any 不同的是,这不是默认实现的。事实上,它在 SDK 中并不存在。但是,您可以自己创建一个。

关键是,任何实现类现在都需要 equals 方法。如果你使用data classes,这不是问题(我已经在代码中证明了这一点)。但是,如果您不这样做,则需要手动实现它。在这里手动要么意味着您编写它,要么您生成它(对于带有注释的实例)。

interface Equatable  
    override fun equals(other: Any?) : Boolean;


// Data classes generate the necessary equals methods. Equatable ensures all child classes do implement it, which fixes what the inspection wants you to fix.
data class One(val t: String) : Equatable  
data class Two(val title: String) : Equatable  

val x = object : DiffUtil.ItemCallback<Equatable /*Or a higher level inheritance model, i.e. a MySharedItemClass, where it either contains an abstract equals or implements Equatable. Implementing it doesn't require it to be abstract, but it depends on where you want the equals implementation. Equatable is an example of forced equals implementation, but there's many ways to Rome. */>() 
    override fun areItemsTheSame(p0: Equatable, p1: Equatable): Boolean 
        TODO("not implemented")
    

    override fun areContentsTheSame(p0: Equatable, p1: Equatable): Boolean 
         return when 
             p0 is One && p1 is One -> true
             p0 is Two && p1 is Two -> p0.title == p1.title
             else -> p0 == p1 // No error!
         
    

【讨论】:

对不起,这可能是一个愚蠢的问题,但MySharedItemClass 是什么?我在您的回答中没有看到它的实现。 @Marat 我不知道。假设这是一个错字,我的意思是Equatable。不知道它来自哪里,但它不应该在那里:')【参考方案2】:

兄弟你只需要在你的 POJO 类中重写 equals() ,瞧这个错误就会消失

【讨论】:

以上是关于Lint 错误:可疑的相等检查:在 Object DiffUtilEquals 中未实现 equals()的主要内容,如果未能解决你的问题,请参考以下文章

Jenkinsfile的语法检查(lint)

错误记录Android Studio 编译时 lint 检查报错 ( Could not resolve junit:junit:4.+. )

如何以编程方式检查/ lint一个Twig模板

错误记录Android Studio 编译时 lint 检查报错 ( WARNING: DSL element ‘android.dataBinding.enabled‘ is obsolet )

如何检查 Perl-CGI 应用程序中的所有错误(例如,使用 Perl 编译器或类似 lint 的工具检查,免费开源?)

AndroidStudio代码检查,Lint检查,还有注解