A melhor maneira de "negar" uma instância de

409

Eu estava pensando se existe uma maneira melhor / mais agradável de negar um instanceofem Java. Na verdade, estou fazendo algo como:

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

Mas acho que deveria existir uma sintaxe "bonita" para fazer isso.

Alguém sabe se existe e como é a sintaxe?


EDIT: Por bonito, eu poderia dizer algo como isto:

if(str !instanceof String) { /* do Something */ } // compilation fails
caarlos0
fonte
24
Eu odeio as regras de precedência para instanceoftanto ...
luiscubal
4
Você pode sempre criar uma variável, algo como boolean strIsString = str instanceof String;...
vaughandroid
Sim, @Baqueta, é uma opção. Mas, que diferenças podem acontecer no uso da memória em uma sintaxe ou em outra?
usar o seguinte código
2
Como isso é um comentário construtivo?
Louth
2
Os criadores de Java podem introduzir uma nova palavra-chave: notinstanceof . Apenas meus dois centavos ^^
Stephan

Respostas:

308

Não, não há melhor caminho; o seu é canônico.

maerics
fonte
132

Não sei o que você imagina quando diz "bonito", mas e quanto a isso? Pessoalmente, acho que é pior do que o formulário clássico que você postou, mas alguém pode gostar ...

if (str instanceof String == false) { /* ... */ }
Natix
fonte
2
Sobre a lógica dupla, você poderia usar em != truevez de == false: D
jupi 16/11
Vendo isso me ajuda a entender que if(!(str instanceof String)) é a única maneira certa, e eu preciso parar de alternativas de pensamento
Vikash
Gosto desta solução, pois não sou obrigado a construir uma pilha de metal enquanto a leio!
JaM 9/08/19
60

Você pode usar o Class.isInstancemétodo:

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

... mas ainda é negado e muito feio.

dacwe
fonte
5
é um pouco melhor, o excesso de parênteses torna o código feio, IMHO.
usar o seguinte código
Isso não é muito mais lento?
Maxammann
4
Isso tem um comportamento diferente. A palavra-chave instanceof inclui subclasses, o método não, você precisa usar Class.isAssignableFrom para replicar o comportamento.
Chris Cooper
7
@ChrisCooper Isso não é verdade:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix
24

Normalmente você não quer apenas ifuma elsecláusula, mas também.

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

pode ser escrito como

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

Ou você pode escrever o código para não precisar saber se é uma String ou não. por exemplo

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

pode ser escrito como

str = str.toString();
Peter Lawrey
fonte
12

Se você pode usar importações estáticas e seu código moral permitir

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

E depois...

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

Este é apenas um exercício de interface fluente, eu nunca usaria isso no código da vida real!
Siga seu jeito clássico, não confundirá mais ninguém lendo seu código!

Pablo Grisafi
fonte
Eu não gosto de importações estáticas .. de qualquer maneira obrigado por tentar ajudar :)
caarlos0
4

Se você achar mais compreensível, poderá fazer algo assim com o 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
}
Paulo
fonte
1
Com o Java 11, isso deve funcionar if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... Não é melhor, imo, mas deve funcionar!
Patrick M
3

ok apenas meus dois centavos, use um método é string:

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
fonte
0

Você pode conseguir fazendo o procedimento abaixo: basta adicionar uma condição adicionando colchete if(!(condition with instanceOf))com toda a condição, adicionando o !operador no início da maneira mencionada nos trechos de código abaixo.

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

ao invés de

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

Concordo que, na maioria dos casos, if (!(x instanceof Y)) {...}é a melhor abordagem, mas, em alguns casos, cria uma isY(x)função para que você possaif (!isY(x)) {...} valer a pena.

Sou iniciante em datilografia, e me deparei com essa questão de S / O várias vezes nas últimas semanas; portanto, para os googlers, a maneira datilografada de fazer isso é criar uma proteção de tipo como esta:

typeGuards.ts

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

uso

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

Eu acho que a única razão pela qual isso pode ser apropriado no texto datilografado e não no js comum é que as proteções tipográficas são uma convenção comum; portanto, se você as escreve para outras interfaces, é razoável / compreensível / natural escrevê-las também para as aulas.

Há mais detalhes sobre proteções de tipo definidas pelo usuário nos documentos

Mr5o1
fonte