ใช้สำหรับประเภทการอ้างอิง Java Void หรือไม่


163

มี Java เป็นVoidตัวพิมพ์ใหญ่ V-- - ชนิดการอ้างอิง สถานการณ์เดียวที่ฉันเคยเห็นมันมาใช้คือการ parameterize Callables

final Callable<Void> callable = new Callable<Void>() {
            public Void call() {
                foobar();
                return null;
            }
        };

มีการใช้งานอื่น ๆ สำหรับVoidประเภทอ้างอิงJava ? จะสามารถมอบหมายสิ่งอื่นนอกเหนือจากนี้ได้nullหรือไม่? ถ้าใช่คุณมีตัวอย่างไหม



คำตอบ:


116

Voidได้กลายเป็นที่ประชุมสำหรับอาร์กิวเมนต์ทั่วไปที่คุณไม่ได้สนใจใน. มีเหตุผลที่คุณควรใช้ชนิดที่ไม่ใช่ instantiable อื่น ๆ Systemไม่เป็นเช่น

มันก็มักจะใช้ในตัวอย่างเช่นMapค่า (ถึงแม้จะCollections.newSetFromMapใช้Booleanเป็นแผนที่ไม่ได้ที่จะยอมรับnullค่า) java.security.PrivilegedActionและ

ฉันเขียนรายการบันทึกทางเว็บเมื่อVoidไม่กี่ปีก่อน


ใครเป็นคนทำอนุสัญญา รัฐเอกสารdocs.oracle.com/javase/tutorial/java/generics/types.html "ประเภทอนุสัญญาการตั้งชื่อพารามิเตอร์โดยการประชุมชื่อพารามิเตอร์ชนิดเป็นอักษรตัวพิมพ์ใหญ่ตัวเดียว"
barlop

4
@barlop เป็นอาร์กิวเมนต์ไม่ใช่ชื่อพารามิเตอร์ java.lang.Voidนั่นคือมันเป็นชนิด / Josh Bloch ทำให้การประชุมเป็นที่นิยมแม้ว่าเมื่อคุณได้เห็นแล้วมันเป็นตัวเลือกที่ชัดเจน
Tom Hawtin - tackline

2
บล็อกนี้นั้นตายแล้ว
mFeinstein

51

คุณสามารถสร้างอินสแตนซ์ของโมฆะโดยใช้การสะท้อนความเห็น แต่สิ่งเหล่านั้นไม่มีประโยชน์อะไรเลย เป็นโมฆะเป็นวิธีการที่บ่งบอกถึงวิธีการทั่วไปไม่ส่งคืนอะไร

Constructor<Void> constructor = Void.class.getDeclaredConstructor();
constructor.setAccessible(true);
Void v = constructor.newInstance();
System.out.println("I have a " + v);

พิมพ์สิ่งที่ชอบ

I have a java.lang.Void@75636731

22
+1 สำหรับอินสแตนซ์คลาสที่เอกสารระบุว่าไม่มีความแน่นอน ฉันได้ทำเช่นนี้แล้วและฉันเห็นด้วยว่าการใช้อินสแตนซ์ของ Voids นั้นไร้ประโยชน์
ลุควู้ดเวิร์ด

1
ตัวสร้าง <Void> cv = Void.class.getDeclaredConstructor (); cv.setAccessible (จริง); Void v = cv.newInstance (); System.out.println (V); //;)
Peter Lawrey

ลองทำคลาสใหม่โดยใช้การสะท้อนและดูว่าเกิดอะไรขึ้น
Peter Lawrey

ฉันได้รับ java.lang.InstantiationException จาก sun.reflect.InstantiationExceptionConstructorAccessorImpl :(
Luke Woodward

7
นี่คือการใช้งานเฉพาะและอาจเปลี่ยนแปลงได้ตลอดเวลา ไม่มีการรับประกันว่าชั้นเรียนจะมีตัวสร้างแบบไม่โต้แย้งและแม้ว่ามันจะมีตัวที่อาจทำอะไรก็ได้ (บางทีSystem.exit(0)) private Void() { throw new Error(); }ฉันมักจะเขียนอาคารเรียนด้วยตัวสร้างเป็น บางคนอาจชอบ enum ที่ไม่มีค่า
Tom Hawtin - tackline

27

Future<Void>ทำงานเหมือนจับใจ :)


6
เป็นเรื่องปกติมากขึ้น (ตัวอย่างเช่นใน Guava) ที่ใช้Future<?>เนื่องจากในอนาคตมักจะมีค่าที่ถูกต้อง (ไม่ใช่Voidประเภท) แต่ใช้ในบริบทที่ไม่สนใจค่า
David Phillips

1
CompletableFuture<Void>ทำงานเหมือนจับใจเช่นกัน
andrybak

19

ระบุว่ามีไม่มีการก่อสร้างสาธารณะnullผมจะบอกว่ามันไม่สามารถกำหนดอะไรอื่นนอกจาก ฉันใช้มันเป็นตัวยึดตำแหน่งสำหรับ "ฉันไม่จำเป็นต้องใช้พารามิเตอร์ทั่วไป" เท่านั้นตามตัวอย่างที่แสดง

มันยังสามารถใช้ในการสะท้อนจากสิ่งที่Javadocพูดว่า:

คลาส Void เป็นคลาสตัวยึดตำแหน่งที่ไม่น่าเชื่อถือเพื่อเก็บการอ้างอิงไปยังวัตถุ Class ที่เป็นตัวแทนของโมฆะคำหลัก Java


ตลกพอที่จะเห็น Oracle / Sun อธิบายอย่างนั้นเป็นโมฆะเป็นตัวอย่างของทุกประเภท อย่างที่คุณพูดความหมายล้วนๆของมันคือ "ฉันสามารถเขียนรูปแบบใด ๆ ที่นี่เพราะฉันไม่สนใจดังนั้นฉันจะทำให้เป็นโมฆะเพื่อให้แน่ใจว่าคนที่อ่านรหัสของฉันเข้าใจว่า"
Snicolas

17

ทุกชั้นเรียนเสื้อคลุมดั้งเดิม ( Integer, Byte, Boolean, Doubleฯลฯ ) มีการอ้างอิงถึงระดับดั้งเดิมที่สอดคล้องกันในแบบคงที่TYPEสนามตัวอย่างเช่น:

Integer.TYPE == int.class
Byte.TYPE == byte.class
Boolean.TYPE == boolean.class
Double.TYPE == double.class

Voidถูกสร้างขึ้นในขั้นต้นเพื่อใช้อ้างอิงถึงvoidประเภท:

Void.TYPE == void.class

Void.TYPEแต่คุณไม่ได้จริงๆได้อะไรโดยใช้ เมื่อคุณใช้void.classจะเห็นได้ชัดว่าคุณทำอะไรกับvoidประเภท

นอกจากนี้ครั้งสุดท้ายที่ฉันลองBeanShellไม่รู้จักvoid.classดังนั้นคุณต้องใช้ที่Void.TYPEนั่น


8
มีทั้ง Void.class และ void.class!
Tom Anderson

8

เมื่อคุณใช้รูปแบบผู้เยี่ยมชมสามารถใช้ Void แทน Object ได้เมื่อคุณต้องการแน่ใจว่าค่าที่ส่งคืนจะเป็นค่าว่าง

ตัวอย่าง

public interface LeavesVisitor<OUT>
{
   OUT visit(Leaf1 leaf);

   OUT visit(Leaf2 leaf);
}

เมื่อคุณจะนำผู้เยี่ยมชมไปใช้คุณสามารถกำหนดให้เป็น Void ได้อย่างชัดเจนเพื่อที่คุณจะได้ทราบว่าผู้เยี่ยมชมของคุณจะกลับมาว่างเปล่าแทนที่จะใช้ Object

public class MyVoidVisitor implements LeavesVisitor<Void>
{
    Void visit(Leaf1 leaf){
        //...do what you want on your leaf
        return null;
    }

    Void visit(Leaf2 leaf){
        //...do what you want on your leaf
        return null;
    }
}

5

ก่อนหน้า generics มันถูกสร้างขึ้นสำหรับ reflection API เพื่อเก็บ TYPE ที่ส่งคืนโดย Method.getReturnType () สำหรับเมธอด void ที่สอดคล้องกับคลาสชนิดดั้งเดิมอื่น ๆ

แก้ไข: จาก JavaDoc ของ Void: "The Void class เป็นตัวยึดตำแหน่งที่ไม่มีความแน่นอนในการเก็บการอ้างอิงไปยังวัตถุ Class ที่เป็นตัวแทนของคำหลัก Java โมฆะ" ก่อนหน้า Generics ฉันรู้ว่าไม่มีประโยชน์ใด ๆ นอกจากการสะท้อนกลับ


ฉันไม่เชื่อสิ่งนี้ ฉันไม่มี JVM ก่อนหน้านี้ที่ 1.4 หรือก่อนหน้านี้ แต่ฉันเชื่อว่า Method.getReturnType () มักจะส่งคืน void.class สำหรับเมธอด void
ลุควู้ดเวิร์ด

@Pour: ฉันกำลังบอกว่าก่อนหน้า generics สิ่งเดียวที่ฉันรู้คือใช้คือถือ TYPE (เหมือนใน Void.TYPE) ซึ่งใช้ใน Method'sget.getReturnType () ของเงาสะท้อน
Lawrence Dol

Voidมันอย่างใดไม่ได้กลับ โปรดดูstackoverflow.com/questions/34248693/…
Alireza Fattahi

3

เนื่องจากคุณไม่สามารถยกตัวอย่าง Void ได้คุณสามารถใช้Apache Commons Null objectได้

Null aNullObject = ObjectUtils.Null;
Null noObjectHere = null;

ในบรรทัดแรกคุณมีวัตถุดังนั้นaNullObject != nullถือในขณะที่ในบรรทัดที่สองไม่มีการอ้างอิงดังนั้นnoObjectHere == nullถือ

เพื่อตอบคำถามเดิมของผู้โพสต์การใช้สิ่งนี้คือการแยกความแตกต่างระหว่าง "ไม่มีอะไร" และ "ไม่มีอะไร" ซึ่งเป็นสิ่งที่แตกต่างอย่างสิ้นเชิง

PS: ปฏิเสธรูปแบบวัตถุ Null


1

โมฆะคือการสร้างการห่อประเภทโมฆะดั้งเดิม ทุกประเภทดั้งเดิมมีประเภทอ้างอิงที่สอดคล้องกัน โมฆะจะใช้ในการยกตัวอย่างคลาสสามัญหรือการใช้วิธีการทั่วไปข้อโต้แย้งทั่วไปแม่มดที่คุณไม่สนใจและนี่คือตัวอย่าง ...

public void onNewRegistration() {
    newRegistrationService.createNewUser(view.getUsername(), view.getPassword(),
            view.getInitialAmount(), view.getCurrency(), new AsyncCallback<Void>() {
      @Override
      public void onFailure(Throwable caught) {

      }

      @Override
      public void onSuccess(Void result) {
        eventBus.fireEvent(new NewRegistrationSuccessEvent());
      }
    });
  } 

ที่นี่อย่างที่คุณเห็นฉันไม่ต้องการอะไรจากเซิร์ฟเวอร์ที่ฉันขอให้สร้างการลงทะเบียนใหม่ แต่public interface AsyncCallback<T> { .... }เป็นอินเทอร์เฟซทั่วไปดังนั้นฉันจึงให้ Void เนื่องจาก generics ไม่ยอมรับประเภทดั้งเดิม


0

นอกจากนี้ยังใช้กันทั่วไปในการเรียกกลับที่เสร็จสิ้น Async-IO เมื่อคุณไม่ต้องการAttachmentวัตถุ ในกรณีที่คุณระบุ null กับการดำเนินงาน IO CompletionHandler<Integer,Void>และดำเนินการ


0

อาจเป็นกรณีที่เกิดขึ้นได้ยาก แต่ครั้งหนึ่งฉันเคยใช้Voidในคลาสมุมมอง

นี่เป็นลักษณะที่ทำงานหลังจากเมธอดที่มี@Logคำอธิบายประกอบและบันทึกเมธอดที่ส่งคืนและข้อมูลบางอย่างถ้าเมธอดส่งคืนชนิดเป็นโมฆะ

 @AfterReturning(value = "@annotation(log)", 
       returning = "returnValue", 
       argNames = "joinPoint, log, returnValue"
      )
    public void afterReturning(final JoinPoint joinPoint, final Log log,
            final Object returnValue) {

            Class<?> returnType = ((MethodSignature) joinPoint.getSignature())
            .getReturnType();
           if (Void.class.isAssignableFrom (returnType)) ) {
            //Do some log
         }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.