instanceofを「無効にする」最良の方法


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年

ええ、@バケタはオプションです。しかし、1つの構文または別の構文でのメモリ使用にどのような違いが生じる可能性がありますか?
caarlos0 2012年

2
その建設的なコメントはどうですか?
ラウス

2
Java作成者は新しいキーワードnotinstanceofを導入する場合があります。ちょうど私の2セント^^
ステファン

回答:



132

あなたが「美しい」と言ったときにあなたが何を想像するかはわかりませんが、これはどうですか?個人的にはあなたが投稿した従来のフォームよりも悪いと思いますが、誰かがそれを気に入るかもしれません...

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

2
ダブルロジックについて!= trueは、== false:Dの代わりに使用できます
jupi

これを見るif(!(str instanceof String)) と、それが唯一の正しい方法であることを理解するのに役立ちます。代替案を考えるのをやめる必要があります
Vikash

私はそれを読んでいる間に金属スタックを構築する必要がないので、私はこの解決策が好きです!
JaM

60

あなたはClass.isInstanceメソッドを使うことができます:

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

...しかし、それはまだ否定され、かなり醜いです。


5
少しカッコいいですが、括弧が多すぎるとコードが見苦しくなります。
caarlos0

これはもっと遅いのでは?
maxammann 2013

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 14

24

通常は、単なる句だけでは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();

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)) { ...です。イモは良くないが、うまくいくはずだ!
Patrick M

3

さて、私の2セントだけです。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ではない唯一の理由は、タイプガードが一般的な規則であるためだと思います。したがって、他のインターフェイス用に記述する場合は、クラス用に記述することも合理的/理解可能/自然なことです。

このようなユーザー定義型ガードの詳細については、ドキュメントにあります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.