La meilleure façon de «nier» une instance de

409

Je pensais s'il existe une meilleure / plus belle façon de nier un instanceofen Java. En fait, je fais quelque chose comme:

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

Mais je pense qu'une "belle" syntaxe pour ce faire devrait exister.

Est-ce que quelqu'un sait si elle existe et à quoi ressemble la syntaxe?


EDIT: Par belle, je pourrais dire quelque chose comme ceci:

if(str !instanceof String) { /* do Something */ } // compilation fails
caarlos0
la source
24
Je déteste les règles de priorité pour instanceoftant de choses ...
luiscubal
4
Vous pouvez toujours créer une variable, quelque chose comme boolean strIsString = str instanceof String;...
vaughandroid
ouais @Baqueta, est une option. Mais, quelles différences pourraient se produire dans l'utilisation de la mémoire dans une syntaxe ou une autre?
caarlos0
2
Comment est-ce un commentaire constructif?
Louth
2
Les créateurs Java peuvent introduire un nouveau mot-clé: notinstanceof . Just my two cents ^^
Stephan

Réponses:

308

Non, il n'y a pas de meilleur moyen; le vôtre est canonique.

maerics
la source
132

Je ne sais pas ce que tu imagines quand tu dis "beau", mais qu'en est-il? Personnellement, je pense que c'est pire que le formulaire classique que vous avez publié, mais quelqu'un pourrait l'aimer ...

if (str instanceof String == false) { /* ... */ }
Natix
la source
2
À propos de la double logique, vous pouvez utiliser à la != trueplace de == false: D
jupi
Voir cela m'aide à comprendre que if(!(str instanceof String)) c'est la seule bonne façon, et je dois arrêter de penser à des alternatives
Vikash
J'aime cette solution car je ne suis pas obligé de construire une pile métallique en la lisant!
JaM
60

Vous pouvez utiliser la Class.isInstanceméthode:

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

... mais c'est toujours nié et assez moche.

dacwe
la source
5
est un peu mieux, l'excès de parenthèses rend le code laid, à mon humble avis.
caarlos0
N'est-ce pas beaucoup plus lent?
maxammann
4
Cela a un comportement différent. Le mot-clé instanceof inclut des sous-classes, mais pas la méthode, vous devez utiliser Class.isAssignableFrom pour répliquer le comportement.
Chris Cooper
7
@ChrisCooper Ce n'est pas vrai:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix
24

Habituellement, vous ne voulez pas seulement ifune elseclause, mais aussi une clause.

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

peut être écrit comme

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

Ou vous pouvez écrire le code afin que vous n'ayez pas besoin de savoir s'il s'agit d'une chaîne ou non. par exemple

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

peut être écrit comme

str = str.toString();
Peter Lawrey
la source
12

Si vous pouvez utiliser des importations statiques et que votre code moral les autorise

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

Et alors...

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

Ceci est juste un exercice d'interface fluide, je ne l'utiliserais jamais dans le code de la vie réelle!
Optez pour votre méthode classique, cela ne gênera personne d'autre à lire votre code!

Pablo Grisafi
la source
Je n'aime pas les importations statiques .. de toute façon merci d'essayer d'aider :)
caarlos0
4

Si vous le trouvez plus compréhensible, vous pouvez faire quelque chose comme ça avec 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
}
Paul
la source
1
Avec Java 11, cela devrait fonctionner if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... Pas mieux, imo, mais ça devrait marcher!
Patrick M
3

ok juste mes deux cents, utilisez une méthode de chaîne 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");
}
tibi
la source
0

Vous pouvez le faire en faisant ci-dessous .. ajoutez simplement une condition en ajoutant un crochet if(!(condition with instanceOf))avec la condition entière en ajoutant l' !opérateur au début juste comme mentionné dans les extraits de code ci-dessous.

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

au lieu de

if(str !instanceof String) { /* do Something */ } // COMPILATION FAIL
Dharmesh Baldha
la source
0

Je suis d'accord que dans la plupart des cas, if (!(x instanceof Y)) {...}c'est la meilleure approche, mais dans certains cas, créer une isY(x)fonction pour que vous puissiez en if (!isY(x)) {...}valoir la peine.

Je suis un novice en dactylographie, et j'ai rencontré cette question S / O plusieurs fois au cours des dernières semaines, donc pour les googleurs, la façon de dactylographier de le faire est de créer un typeguard comme celui-ci:

typeGuards.ts

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

usage

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

Je suppose que la seule raison pour laquelle cela pourrait être approprié en dactylographié et non en js normal est que les garde-types sont une convention courante, donc si vous les écrivez pour d'autres interfaces, il est raisonnable / compréhensible / naturel de les écrire pour les classes aussi.

Il y a plus de détails sur les protecteurs de type définis par l'utilisateur comme celui-ci dans la documentation

Mr5o1
la source