【问题标题】:Best way to "negate" an instanceof“否定” instanceof 的最佳方法
【发布时间】:2012-02-22 11:59:33
【问题描述】:

我在想是否存在更好/更好的方法来否定 Java 中的 instanceof。 实际上,我正在做类似的事情:

if(!(str instanceof String)) { /* do Something */ }

但我认为应该存在一种“漂亮”的语法来做到这一点。

有谁知道它是否存在,以及语法是什么样的?


编辑: 对于美丽,我可能会这样说:

if(str !instanceof String) { /* do Something */ } // compilation fails

【问题讨论】:

  • 我非常讨厌instanceof 的优先规则...
  • 你总是可以创建一个变量,比如boolean strIsString = str instanceof String;...
  • 是的@Baqueta,是一个选项。但是,在一种或另一种语法中,内存使用会发生什么差异?
  • 这是一个建设性的评论吗?
  • Java 创建者可能会引入一个新关键字:notinstanceof。只是我的两分钱^^

标签: java syntax


【解决方案1】:

不,没有更好的方法;你的是规范的。

【讨论】:

    【解决方案2】:

    我不知道当你说“美丽”时你会想到什么,但是这个呢?我个人认为它比您发布的经典表格更糟糕,但有人可能会喜欢它...

    if (str instanceof String == false) { /* ... */ }
    

    【讨论】:

    • 关于双重逻辑,你可以用!= true代替== false:D
    • 看到这让我明白if(!(str instanceof String))是唯一正确的方法,我需要停止思考替代方案
    • 我喜欢这个解决方案,因为我不需要在阅读时建立金属堆栈!
    • SonarLint 将报告有关此编码形式的问题(作为次要代码气味),消息是:删除文字“false”布尔值。
    • 静态代码检查器抱怨这一点,但我更喜欢这个,那个小的 ! 字符很容易被忽视......我会说有很多“我们”,例如与 !isBlank() 相比,StringUtils 提供 isBlank()isNotBlank()...
    【解决方案3】:

    您可以使用Class.isInstance 方法:

    if(!String.class.isInstance(str)) { /* do Something */ }
    

    ...但它仍然被否定并且非常丑陋。

    【讨论】:

    • 好一点,多余的括号使代码很难看,恕我直言。
    • 这不是慢很多吗?
    • 这有不同的行为。 instanceof 关键字包含子类,方法不包含,需要使用 Class.isAssignableFrom 来复制行为。
    • @ChrisCooper 这不是真的:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
    【解决方案4】:

    通常您不仅需要if,还需要else 子句。

    if(!(str instanceof String)) { /* do Something */ } 
    else { /* do something else */ }
    

    可以写成

    if(str instanceof String) { /* do Something else */ } 
    else { /* do something */ }
    

    或者您可以编写代码,这样您就不需要知道它是否为字符串。例如

    if(!(str instanceof String)) { str = str.toString(); } 
    

    可以写成

    str = str.toString();
    

    【讨论】:

    • 我认为这是最好的答案(第一部分)
    • 这必须是一个可以接受的答案,因为 IntelliJ 也建议了这种方法。
    【解决方案5】:

    如果您可以使用静态导入,并且您的道德准则允许它们

    public class ObjectUtils {
        private final Object obj;
        private ObjectUtils(Object obj) {
            this.obj = obj;
        }
    
        public static ObjectUtils thisObj(Object obj){
            return new ObjectUtils(obj);
        }
    
        public boolean isNotA(Class<?> clazz){
            return !clazz.isInstance(obj);
        }
    }
    

    然后……

    import static notinstanceof.ObjectUtils.*;
    
    public class Main {
    
        public static void main(String[] args) {
            String a = "";
            if (thisObj(a).isNotA(String.class)) {
                System.out.println("It is not a String");
            }
            if (thisObj(a).isNotA(Integer.class)) {
                System.out.println("It is not an Integer");
            }
        }    
    }
    

    这只是一个流畅的界面练习,我永远不会在实际代码中使用它!
    采用您的经典方式,它不会让其他人阅读您的代码感到困惑!

    【讨论】:

    • 我不喜欢静态导入.. 无论如何感谢您的帮助:)
    【解决方案6】:

    如果你觉得它更容易理解,你可以用 Java 8 做这样的事情:

    public static final Predicate<Object> isInstanceOfTheClass = 
        objectToTest -> objectToTest instanceof TheClass;
    
    public static final Predicate<Object> isNotInstanceOfTheClass = 
        isInstanceOfTheClass.negate(); // or objectToTest -> !(objectToTest instanceof TheClass)
    
    if (isNotInstanceOfTheClass.test(myObject)) {
        // do something
    }
    

    【讨论】:

    • 对于 Java 11,这应该可以工作 if (Predicate.not(isInstanceOfTheClass).test(myObject)) { ...。不是更好,imo,但应该可以!
    【解决方案7】:

    好吧,我的两分钱,使用一个是字符串方法:

    public static boolean isString(Object thing) {
        return thing instanceof String;
    }
    
    public void someMethod(Object thing){
        if (!isString(thing)) {
            return null;
        }
        log.debug("my thing is valid");
    }
    

    【讨论】:

      【解决方案8】:

      您可以通过以下方式实现.. 只需通过添加括号if(!(condition with instanceOf)) 来添加条件,并通过在开头添加! 运算符来添加整个条件,就像下面代码 sn-ps 中提到的方式一样。

      if(!(str instanceof String)) { /* do Something */ } // COMPILATION WORK
      

      而不是

      if(str !instanceof String) { /* do Something */ } // COMPILATION FAIL
      

      【讨论】:

        【解决方案9】:

        我同意在大多数情况下if (!(x instanceof Y)) {...} 是最好的方法,但在某些情况下创建一个isY(x) 函数以便if (!isY(x)) {...} 是值得的。

        我是一个打字稿新手,在过去的几周里,我已经多次遇到这个 S/O 问题,所以对于谷歌人来说,打字稿的方法是创建一个这样的 typeguard:

        typeGuards.ts

        export function isHTMLInputElement (value: any): value is HTMLInputElement {
          return value instanceof HTMLInputElement
        }
        

        用法

        if (!isHTMLInputElement(x)) throw new RangeError()
        // do something with an HTMLInputElement
        

        我猜这可能适用于 typescript 而不是常规 js 的唯一原因是 typeguard 是一种常见的约定,因此如果您为其他接口编写它们,那么为类编写它们也是合理/可理解/自然的.

        有更多关于用户定义类型保护的详细信息,例如in the docs

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-03
          • 2011-01-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-08
          • 2012-04-01
          • 2016-12-30
          相关资源
          最近更新 更多