“否定”实例的最佳方法


409

我在想是否存在一种更好/更巧妙的方法来否定instanceofJava。实际上,我正在执行以下操作:

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

但是我认为应该存在一种“美丽”的语法。

有谁知道它是否存在以及其语法如何?


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

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

24
我非常讨厌优先规则instanceof……
luiscubal 2012年

4
您总是可以创建一个变量,例如boolean strIsString = str instanceof String;...
vaughandroid 2012年

是的@Baqueta,是一个选择。但是,以一种或另一种语法在内存使用方面可能会发生什么差异?
caarlos0 2012年

2
这个建设性评论如何?
Louth's

2
Java创建者可以引入一个新关键字:notinstanceof。只是我的两分钱^^
斯蒂芬

Answers:



132

我不知道您说“美丽”时的想法,但是那又如何呢?我个人认为这要比您发布的经典表格差,但有人可能会喜欢...

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

2
关于双重逻辑,您可以使用:D != true代替== false
jupi,

看到这一点有助于我理解这if(!(str instanceof String)) 是唯一正确的方法,并且我需要停止思考替代方案
Vikash

我喜欢此解决方案,因为在阅读时不需要构建金属堆栈!
JaM

59

您可以使用以下Class.isInstance方法:

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

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


5
好一点了,多余的括号使代码难看,恕我直言。
caarlos0 2012年

这不是慢很多吗?
maxammann

4
这有不同的行为。instanceof关键字包括子类,该方法不包括,您需要使用Class.isAssignableFrom复制行为。
克里斯·库珀

7
@ChrisCooper这不是真的:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix 2014年

24

通常,您也不要只想要if一个else子句。

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

可以写成

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

或者,您可以编写代码,这样就无需知道它是否为String。例如

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

可以写成

str = str.toString();

12

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

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

这只是一个流畅的界面练习,我绝对不会在现实生活中使用它!
以您的经典方式走,它不会混淆其他人阅读您的代码!


我不喜欢静态导入。无论如何,感谢您的帮助:)
caarlos0 2012年

4

如果您觉得它更容易理解,则可以使用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
}

1
对于Java 11,这应该可以工作if (Predicate.not(isInstanceOfTheClass).test(myObject)) { ...。更好,imo,但应该可以!
Patrick M

3

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

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

0

您可以通过以下方式实现。.只需通过在代码开头if(!(condition with instanceOf))添加!操作符的方式,将括号与整个条件一起添加条件即可,如下面的代码片段所述。

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

代替

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

0

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

我是打字稿新手,并且在过去几周内多次遇到这个S / O问题,因此对于Google员工来说,打字稿的实现方法是创建这样的打字亭:

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是一个通用约定,因此,如果要为其他接口编写它们,那么为类编写它们也是合理/可以理解/自然的。

在文档中有关于用户定义类型防护的更多详细信息

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.