草庐IT

无法确定是否相等时,Java 等于

coder 2023-08-31 原文

我想知道什么是正确的 Java 编程范式来覆盖类 C 对象的 equals(和 hashCode)方法,在以下情况下 (a) 有没有足够的信息来确定 C 的两个实例是否相等,或者 (b) 调用方法不应该能够确定 C 的两个实例是否相等。

例如,在我的项目中,我有一个 PlayingCard 类。在我看来,如果 PlayingCard 面朝上,那么调用方法应该可以访问它的属性,但如果面朝下,那么这些属性应该保持未知:

class PlayingCard {
    private Rank rank;
    private Suit suit;
    private boolean isFaceDown;

    public PlayingCard(Rank rank, Suit suit, boolean isFaceDown) {
        this.rank = rank;
        this.suit = suit;
        this.isFaceDown = isFaceDown;
    }

    public Rank getRank() { return isFaceDown ? null : rank; }

    public Suit getSuit() { return isFaceDown ? null : suit; }

看起来,为了 Java 集合框架的缘故,如果两张扑克牌的点数和花色相同,则它们应该相等:

    public boolean equals(Object obj) {       // attempt #1
        if(this == obj) return true;
        if(obj == null) return false;
        if(!(obj instanceof PlayingCard)) return false;
        PlayingCard other = (PlayingCard) obj;
        if(rank != other.rank) return false;
        if(suit != other.suit) return false;
        return true;
    }
 }

但这揭示了太多信息:

class Malicious {

    public Rank determineRankOfFaceDownCard(PlayingCard faceDownCard) {
        Set<PlayingCard> allCards = /* a set of all 52 PlayingCards face up */;
        for(PlayingCard c : allCards) {
            if(c.equals(faceDownCard)) {
                return c.getRank();
            }
        }
        return null;
    }
}

使用 getRank 和 getSuit` 方法似乎也不起作用:

    public boolean equals(Object obj) {       // attempt #1
        if(this == obj) return true;
        if(obj == null) return false;
        if(!(obj instanceof PlayingCard)) return false;
        PlayingCard other = (PlayingCard) obj;
        if(getRank() != other.getRank()) return false;
        if(getSuit() != other.getSuit()) return false;
        return true;
    }
}

/* outside the PlayingCard class */

Set<PlayingCard> s = new HashSet<PlayingCard>();
s.add(new PlayingCard(Rank.ACE, Suit.SPADES, true));
s.contains(new PlayingCard(Rank.TWO, Rank.HEARTS, true)); // returns true

其他开发者是如何处理这种情况的?在这种情况下抛出某种 RuntimeException 是否合适?感谢您的任何意见和想法。

最佳答案

您可以在 equals 方法中添加此条件:

if(this.isFaceDown || other.isFaceDown) return false;

我认为这是将牌面朝下完全隐藏的唯一方法。问题是,将其添加到集合中时,如果您要添加的卡片面朝下,则可能会出现重复。

关于无法确定是否相等时,Java 等于,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11104195/

有关无法确定是否相等时,Java 等于的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  4. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  5. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  6. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  7. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  8. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  9. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  10. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

随机推荐