Лучший способ «отрицать» экземпляр


409

Я думал, существует ли лучший / более хороший способ отрицать instanceofв Java. На самом деле я делаю что-то вроде:

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

Но я думаю, что «красивый» синтаксис для этого должен существовать.

Кто-нибудь знает, существует ли он и как выглядит синтаксис?


РЕДАКТИРОВАТЬ: красивым, я мог бы сказать что-то вроде этого:

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

24
Я ненавижу правила предшествования за instanceofтак много ...
luiscubal

4
Вы всегда можете создать переменную, что-то вроде boolean strIsString = str instanceof String;...
vaughandroid

да @Baqueta, это вариант. Но какие различия могут возникнуть при использовании памяти в том или ином синтаксисе?
caarlos0

2
Как это конструктивный комментарий?
Лаут

2
Создатели Java могут ввести новое ключевое слово: notinstanceof . Просто мои два цента ^^
Стефан

Ответы:



132

Я не знаю, что вы представляете, когда говорите «красиво», но как насчет этого? Лично я думаю, что это хуже, чем классическая форма, которую вы разместили, но кому-то это может понравиться

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

2
О двойной логике можно было бы использовать != trueвместо == false: D
jupi

Видя это, я понимаю, что if(!(str instanceof String)) это единственный правильный путь, и мне нужно перестать думать об альтернативах
Викаш

Мне нравится это решение, так как я не обязан создавать металлический стек во время чтения!
JAM

60

Вы можете использовать Class.isInstanceметод:

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

... но это все еще отрицается и довольно некрасиво.


5
немного лучше, лишние скобки делают код некрасивым, ИМХО.
caarlos0

Разве это не намного медленнее?
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

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

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)) { .... Не лучше, имо, но должно работать!
Патрик М

3

хорошо, только мои два цента, используйте метод строки:

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 несколько раз за последние несколько недель, поэтому для googlers способ машинописи сделать это - создать такую ​​защиту:

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

Я предполагаю, что единственная причина, по которой это может быть уместно в машинописном тексте, а не в обычном js, заключается в том, что типографские символы - это общее соглашение, поэтому, если вы пишете их для других интерфейсов, разумно / понятно / естественно написать их также для классов.

Там больше подробно о пользовательских определяемых типах охранников как это в документах

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.