ChatGPT解决这个技术问题 Extra ChatGPT

“否定” instanceof 的最佳方法

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

if(!(myObject instanceof SomeClass)) { /* do Something */ }

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

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

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

if(myObject !instanceof SomeClass) { /* do Something */ } // compilation fails
我非常讨厌 instanceof 的优先规则...
您总是可以创建一个变量,例如 boolean strIsString = str instanceof String;...
是的@Baqueta,是一种选择。但是,以一种或另一种语法使用内存时会发生什么差异?
这是一个建设性的评论吗?
Java 创建者可能会引入一个新关键字:notinstanceof。只是我的两分钱^^

m
maerics

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


实际上可能是这样的: if (!(obj instanceof String)) - 工作得很好!
@arun 这是我们都讨厌的语法,最初的发帖人在问如何避免。
T
ThomasW

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

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

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

您可以使用 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)
K
Koray Tugay

通常,您不仅需要 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 也建议使用这种方法。
这可能只是一个“我”的问题,但如果不是,并且其他人处于类似情况,我想至少添加评论,即我对第一部分的第一次阅读是“大多数时候总是包含一个很好的做法else 为您的 if,即使它只是一个无操作”,我称之为糟糕的建议。我现在意识到我看错了,但想放弃这个笔记,以防其他人也看错了。很好的答案!
P
Pablo Grisafi

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

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");
        }
    }    
}

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


我不喜欢静态导入..无论如何感谢您的帮助:)
P
Paul

如果你觉得它更容易理解,你可以用 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,但应该工作!
t
tibi

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

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");
}

D
Dharmesh Baldha

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

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

代替

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

M
Mr5o1

我同意在大多数情况下 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