【问题标题】:Why does this work? (SameAs vs ==)为什么这行得通? (SameAs vs ==)
【发布时间】:2016-04-28 13:21:57
【问题描述】:

我有一个问题:

Why is this not working sometimes?

我正在比较位图并相应地执行代码,但代码没有执行。我的问题得到了很多很好的答案。一个有效的答案建议删除==,并将其更改为.sameAs(),以使我的应用程序可以在较新的手机上运行。

ClickGround = v.getBackground(); //Get the background of button clicked (ClickGround is a bitmap)
        BitClick = ((BitmapDrawable) ClickGround).getBitmap(); //the bitmap background of the button clicked

那么,为什么使用sameAs() 方法比使用== 来比较位图更有效?另外,为什么使用== 在较低版本的android (kitkat) 中工作,和sameAs 更高版本?

谢谢,

鲁基尔

【问题讨论】:

  • 如果您在链接的问题中注意到,您会看到第一个答案说明了“我如何比较不同的对象”。为什么?

标签: java android performance bitmap drawable


【解决方案1】:

那么,为什么使用 sameAs() 方法比使用 == 来比较位图更有效?

它没有更有效地工作。当==工作时,比sameAs()效率更高。

但是,sameAs()== 不起作用的情况下有效。这就是您应该使用sameAs() 而不是== 来比较位图的原因。

另外,为什么在较低版本的 android (kitkat) 中使用 == 有效,而在较高版本中使用相同?

在较新的版本中,Bitmap 对象的创建和共享(或不共享)方式发生了一些变化。当您使用== 进行测试时,您依赖的是未记录的实现特定行为。这种行为已经改变。

为什么变了?我的猜测是,这是对幕后位图缓存机制进行更改的副作用。

【讨论】:

    【解决方案2】:

    == 是一个关系运算符,因此实际上只适用于数字代表值

    但是,sameAs() 正在查看包含的 DATA,而不是整个文件及其相关内容。

    例如:

    int a = 3; 
    String b = "3"; 
    

    我们知道 3 是一个数值,“3”是一个表示数值的字符串。对于普通人来说,它们都代表相同的东西,但是是计算机。在这种情况下,如果您尝试比较

    if (a==b){//something}
    

    我们知道我们必须进行某种翻译,因为这两者对于计算机来说是不同的。

    有点像

    if (Integer.parseInt("b") == a){//do something}
    

    会被需要甚至

    if( Integer.toString(a).equals(b)){//do something)
    

    在图像的情况下,两者具有完全不同的位置和其他参考,因此对于 == 类型比较,它们永远不会是“等价的”。即使两者都是字符串,它们在内存中的保存位置也不同,关联值也不同,这就是使用 .equals() 的原因。

    就位图而言,它们是一种抽象数据类型,因此即使equals() 也不适用于此处。因为你需要比较抽象数据包含sameAs()被使用。

    【讨论】:

    • 那我什么时候应该使用equals() 而不是sameAs()
    • 这取决于所讨论的课程。最佳实践是 值对象 覆盖 equals 以允许进行更有意义的相等比较(否则它默认为身份,这与我在回答中描述的 == 相同)。无论出于何种原因,Android Bitmap 类都不会覆盖equals(),而是以基本相同的目的定义sameAs()。我不知道为什么,但你总是可以为此提出一个新问题。
    • 请记住,Android 在位图方面有一些有趣的东西,以 MediaStore API 为例。在这种情况下,sameAs() 与 equals 的返回“值”不同。它必须实际“查看”位图并使用 sameAs 比较,因为它们是抽象数据类型,而 equals 不适用于这些情况。这个例子真的是为了让人理解它。
    【解决方案3】:

    需要明确的是,sameAs() 并不能“更有效地”工作,而是唯一能正确/可靠工作的。这是因为== 只决定两个对象是否相同——即指向同一个对象——但即使对于完全相同但恰好是不同对象的位图也可能返回 false。

    您正在调用的方法可能在某些设备上和在 API 的合同内,为同一个位图返回不同的对象,因此 == 将返回 false。如果位图相同,sameAs() 将返回 true(与所有属性相同):

    Given another bitmap, return true if it has the same dimensions, config,
    and pixel data as this bitmap. If any of those differ, return false. If 
    other is null, return false. 
    

    背后的想法是一样的:

    void foo(Integer a, Integer b) {
      if (a == b) {
       ...
      }
    }
    

    这几乎肯定是错误的 - 你通常想要 a.equals(b) 或者 Objects.equals(a, b) 如果 a 可以为空,否则甚至调用如下:

    foo(1234, 1234)

    上面的比较通常会失败。

    【讨论】:

    • 所以只有当对象属于同一类时才有效?
    • 没有。也就是说,我不确定您所说的“它有效”是什么意思,但它与课程并没有真正的关系。一个好的经验法则是,至少在您充分理解这一点之前,您应该几乎从不使用== 来比较对象。您几乎总是使用equals 或其他类似方法来确定对象是否相同。对于 Bitmap,该方法是 `sameAs()。
    • 好的,让我重新表述我的问题。您如何定义“两个对象相同”?
    • 在java语言规范的特定上下文中,相同的对象引用意味着引用指向同一个对象。例如,在 sn-p 中:Integer a = new Integer(1), b = a;ab 相同,a == b 因为它们都指向同一个对象。但是,在这种情况下:Integer a = new Integer(1), b = new Integer(1);,它们 相同,而a != bab 的值都为 1,因此它们“相同”或“相等”,但不完全相同(正式而言),因为它们指向不同的对象。
    猜你喜欢
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-02
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多