当前位置: 首页 > 面试题库 >

避免在Java中使用instanceof

浦修文
2023-03-14
问题内容

具有“ instanceof”操作链被认为是“代码异味”。标准答案是“使用多态性”。在这种情况下我该怎么办?

基类有许多子类。他们都不在我的控制之下。类似的情况是Java类Integer,Double,BigDecimal等。

if (obj instanceof Integer) {NumberStuff.handle((Integer)obj);}
else if (obj instanceof BigDecimal) {BigDecimalStuff.handle((BigDecimal)obj);}
else if (obj instanceof Double) {DoubleStuff.handle((Double)obj);}

我确实可以控制NumberStuff等。

我不想使用几行代码就能完成的代码。(有时,我制作了一个HashMap将Integer.class映射到IntegerStuff的实例,将BigDecimal.class映射到BigDecimalStuff的实例,等等。但是今天我想要一些更简单的方法。)

我想要这样简单的东西:

public static handle(Integer num) { ... }
public static handle(BigDecimal num) { ... }

但是Java不能那样工作。

我想在格式化时使用静态方法。我正在格式化的东西是复合的,其中Thing1可以包含Thing2s数组,Thing2可以包含Thing1s数组。当实现这样的格式化程序时,我遇到了一个问题:

class Thing1Formatter {
  private static Thing2Formatter thing2Formatter = new Thing2Formatter();
  public format(Thing thing) {
      thing2Formatter.format(thing.innerThing2);
  }
}
class Thing2Formatter {
  private static Thing1Formatter thing1Formatter = new Thing1Formatter();
  public format(Thing2 thing) {
      thing1Formatter.format(thing.innerThing1);
  }
}

是的,我知道HashMap和更多的代码也可以解决该问题。但是通过比较,“ instanceof”似乎是如此可读和可维护。有没有简单但没有臭味的东西?

事实证明,将来可能会添加新的子类,而我现有的代码将不得不优雅地处理它们。在这种情况下,基于HashMap的类将无法正常工作,因为找不到该类。从最具体的开始到最一般的结束的一串if语句可能毕竟是最好的:

if (obj instanceof SubClass1) {
    // Handle all the methods and properties of SubClass1
} else if (obj instanceof SubClass2) {
    // Handle all the methods and properties of SubClass2
} else if (obj instanceof Interface3) {
    // Unknown class but it implements Interface3
    // so handle those methods and properties
} else if (obj instanceof Interface4) {
    // likewise.  May want to also handle case of
    // object that implements both interfaces.
} else {
    // New (unknown) subclass; do what I can with the base class
}

问题答案:

你可能对Steve Yegge的Amazon博客中的条目感兴趣:“多态性失败时”。本质上,他正在解决这样的情况,即多态性带来的麻烦多于解决的麻烦。

问题是要使用多态性,你必须使每个“切换”类的“句柄”逻辑(在这种情况下为Integer等)成为一部分。显然,这是不切实际的。有时从逻辑上讲,这甚至都不是放置代码的正确位置。他建议采用“ instanceof”方法,以减少一些弊端。

与所有被迫编写有臭味的代码的情况一样,请以一种方法(或最多一类)将其保持扣紧状态,以使气味不会泄漏出去。



 类似资料:
  • 问题内容: 我有以下(也许是常见的)问题,此刻绝对使我感到困惑: 有几个生成的事件对象扩展了抽象类,我想将它们划分为Session Bean,例如 但是将来可能会有两种以上的事件类型,因此if- else将会很长,甚至可能无法读取。另外,在这种情况下,我认为这并不是真正的“最佳实践”。 我可以在类型中添加一个抽象方法,并让它们自行划分,但随后我必须在每个实体中注入特定的Session Bean。

  • 问题内容: 建议在HTML页面中使用表格(现在已经有了CSS)? 表格有什么用途?表具有哪些CSS所没有的功能? 问题答案: 一点都不。但是将表格用于表格数据。只是不要将它们用于一般布局。 但是,如果您显示表格数据(例如结果或什至是表格),请继续使用表格!

  • 问题内容: 我已经编写了类似这样的方法。但是我猜这应该进行重构。谁能建议最好的方法来避免使用多个if语句? 我在这里不能使用大小写转换,因为我的“条件”是。 问题答案: 您可以使用来保存您的解决方案: 为了使此代码起作用,您需要像在类中那样进行定义和定义,如下所示:

  • 问题内容: Process p = Runtime.getRuntime().exec(command); is = p.getInputStream(); byte[] userbytes = new byte[1024]; is.read(userbytes); 我想从java在linux os中执行shell命令。但是Pmd报告说不要使用Java Runtime.exec()。为什么?是什么

  • 从我的main开始,我将启动两个线程,称为producer和consumer。两者都包含循环。生产者循环是UDP服务器,因此不需要Hibernate。我的问题出在消费者方面。使用者循环将对象从链接队列中移除,并将其传递给一个函数进行进一步处理。根据研究,在循环中使用线程Hibernate不是一个好的实践,因为有时O/S在设定时间结束时不会释放。如果我删除线程Hibernate,当应用程序是理想的,

  • 问题内容: 每当关于Java同步的问题浮出水面时,有些人就会很想指出应该避免的事情。他们声称,取而代之的是,最好是锁定私有引用。 给出的一些原因是: 一些邪恶的代码可能会窃取你的锁(非常流行,也有一个“偶然”的变体) 同一类中的所有同步方法都使用完全相同的锁,这会降低吞吐量 你(不必要地)暴露了太多信息 包括我在内的其他人则认为,这是一个惯用语言(在Java库中也是如此),是安全且易于理解的。应当