Cách tốt nhất để phủ nhận


409

Tôi đã suy nghĩ nếu có tồn tại một cách tốt hơn / đẹp hơn để phủ định một instanceoftrong Java. Trên thực tế, tôi đang làm một cái gì đó như:

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

Nhưng tôi nghĩ rằng một cú pháp "đẹp" để làm điều này nên tồn tại.

Có ai biết nếu nó tồn tại, và cú pháp trông như thế nào?


EDIT: Bởi đẹp, tôi có thể nói một cái gì đó như thế này:

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

24
Tôi ghét các quy tắc ưu tiên instanceofrất nhiều ...
luiscubal

4
Bạn luôn có thể tạo một biến, đại loại như boolean strIsString = str instanceof String;...
vaughandroid

vâng @Baqueta, là một lựa chọn. Nhưng, sự khác biệt nào có thể xảy ra trong việc sử dụng bộ nhớ theo cú pháp này hay cú pháp khác?
caarlos0

2
Làm thế nào là một nhận xét mang tính xây dựng?
Louth

2
Những người tạo Java có thể giới thiệu một từ khóa mới: notinstanceof . Chỉ hai xu của tôi ^^
Stephan

Câu trả lời:


308

Không, không có cách nào tốt hơn; của bạn là kinh điển.


132

Tôi không biết những gì bạn tưởng tượng khi bạn nói "đẹp", nhưng điều này thì sao? Cá nhân tôi nghĩ nó tệ hơn hình thức cổ điển mà bạn đã đăng, nhưng ai đó có thể thích nó ...

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

2
Về logic kép, bạn có thể sử dụng != truethay vì == false: D
jupi

Thấy điều này giúp tôi hiểu đó if(!(str instanceof String)) là cách duy nhất đúng đắn và tôi cần ngừng suy nghĩ thay thế
Vikash

Tôi thích giải pháp này vì tôi không bắt buộc phải xây dựng một chồng kim loại trong khi đọc nó!
JaM

60

Bạn có thể sử dụng Class.isInstancephương pháp:

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

... nhưng nó vẫn bị phủ nhận và khá xấu xí.


5
tốt hơn một chút, dấu ngoặc đơn thừa làm cho mã xấu, IMHO.
caarlos0

Đây không phải là chậm hơn nhiều sao?
maxammann

4
Điều này có hành vi khác nhau. Từ khóa instanceof bao gồm các lớp con, phương thức thì không, bạn cần sử dụng Class.isAssignableFrom để sao chép hành vi.
Chris Cooper

7
@ChrisCooper Điều này không đúng:this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses)
Natix

24

Thông thường bạn không muốn chỉ là ifmột elseđiều khoản.

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

có thể được viết như

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

Hoặc bạn có thể viết mã để bạn không cần biết đó có phải là Chuỗi hay không. ví dụ

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

có thể được viết như

str = str.toString();

12

Nếu bạn có thể sử dụng nhập khẩu tĩnh và mã đạo đức của bạn cho phép chúng

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

Và sau đó...

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

Đây chỉ là một bài tập giao diện trôi chảy, tôi sẽ không bao giờ sử dụng nó trong mã thực tế!
Theo cách cổ điển của bạn, nó sẽ không gây nhầm lẫn cho bất kỳ ai khác đọc mã của bạn!


Tôi không thích nhập tĩnh .. dù sao cũng cảm ơn vì đã cố gắng giúp đỡ :)
caarlos0

4

Nếu bạn thấy dễ hiểu hơn, bạn có thể làm điều gì đó như thế này với 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
Với Java 11, điều này sẽ hoạt động if (Predicate.not(isInstanceOfTheClass).test(myObject)) { .... Không tốt hơn, imo, nhưng nên làm việc!
Patrick M

3

ok chỉ hai xu của tôi, sử dụng một phương thức chuỗi:

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

Bạn có thể đạt được bằng cách thực hiện theo cách bên dưới .. chỉ cần thêm một điều kiện bằng cách thêm dấu ngoặc if(!(condition with instanceOf))với toàn bộ điều kiện bằng cách thêm !toán tử khi bắt đầu theo cách được đề cập trong đoạn mã dưới đây.

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

thay vì

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

0

Tôi đồng ý rằng trong hầu hết các trường hợp, đó if (!(x instanceof Y)) {...}là cách tiếp cận tốt nhất, nhưng trong một số trường hợp, việc tạo một isY(x)hàm để bạn có thể có if (!isY(x)) {...}giá trị.

Tôi là người mới viết bản thảo, và tôi đã vấp phải câu hỏi S / O này rất nhiều lần trong vài tuần qua, vì vậy, đối với các nhân viên Google, cách thức bản in để làm điều này là tạo ra một kiểu chữ như thế này:

typeGuards.ts

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

sử dụng

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

Tôi đoán lý do duy nhất tại sao điều này có thể phù hợp trong bản in và không phải js thông thường là các kiểu chữ là quy ước chung, vì vậy nếu bạn viết chúng cho các giao diện khác, thì cũng hợp lý / dễ hiểu / tự nhiên để viết chúng cho các lớp.

Có nhiều chi tiết hơn về các loại bảo vệ do người dùng định nghĩa như thế này trong các tài liệu

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.