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


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.