วิธีที่ดีที่สุดในการ "ปฏิเสธ" อินสแตนซ์ของ


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
ความคิดเห็นที่สร้างสรรค์เป็นอย่างไร
Louth

2
ผู้สร้าง Java อาจนำคำหลักใหม่: notinstanceof แค่สองเซ็นต์ของฉัน ^^
เตฟาน

คำตอบ:



132

ฉันไม่รู้ว่าคุณคิดอย่างไรเมื่อคุณพูดว่า "สวย" แต่แล้วเรื่องนี้ล่ะ? ฉันคิดว่ามันแย่กว่ารูปแบบดั้งเดิมที่คุณโพสต์ แต่บางคนอาจชอบมัน ...

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

2
เกี่ยวกับตรรกะคู่คุณสามารถใช้!= trueแทน== false: D
jupi

การเห็นสิ่งนี้ช่วยให้ฉันเข้าใจว่าif(!(str instanceof String)) เป็นวิธีที่ถูกต้องและฉันต้องหยุดคิดทางเลือกอื่น ๆ
Vikash

ฉันชอบวิธีนี้เนื่องจากฉันไม่จำเป็นต้องสร้างสแต็คโลหะในขณะที่อ่าน!
JaM

59

คุณสามารถใช้Class.isInstanceวิธีการ:

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

... แต่มันก็ยังไร้ซึ่งความน่าเกลียด


5
ดีกว่านิดหน่อยเครื่องหมายวงเล็บส่วนเกินทำให้โค้ดน่าเกลียด IMHO
caarlos0

นี่มันช้ากว่าหรือเปล่า?
maxammann

4
สิ่งนี้มีพฤติกรรมที่แตกต่าง คำหลัก instanceof มีคลาสย่อยซึ่งเป็นวิธีการที่ไม่จำเป็นต้องใช้ Class.isAssignableFrom เพื่อทำซ้ำพฤติกรรม
Chris Cooper

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)) { ...นี้ควรจะทำงาน ไม่ดีกว่า IMO แต่ควรได้ผล!
Patrick M

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 นี้มาหลายครั้งในช่วงสองสามสัปดาห์ที่ผ่านมาดังนั้นสำหรับผู้ใช้ Google ในการพิมพ์ตัวพิมพ์ดีดแบบนี้เพื่อสร้างตัวพิมพ์ดีดเช่นนี้:

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

ฉันเดาเหตุผลเดียวว่าทำไมสิ่งนี้ถึงเหมาะสมใน typescript และไม่ใช่ js ปกติก็คือ typeguards เป็นแบบแผนทั่วไปดังนั้นถ้าคุณเขียนมันสำหรับอินเตอร์เฟสอื่นมันสมเหตุสมผล / เข้าใจได้ / เป็นธรรมชาติที่จะเขียนมันสำหรับคลาสด้วย

มีรายละเอียดเพิ่มเติมเกี่ยวกับการ์ดชนิดที่ผู้ใช้กำหนดเช่นนี้ในเอกสาร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.