Penggunaan untuk Jenis Referensi Java Void?

163

Ada tipe referensi Java Void- huruf besar V-- . Satu-satunya situasi yang pernah saya lihat adalah menggunakan parameterize s Callable

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

Apakah ada kegunaan lain untuk Voidtipe referensi Java ? Bisakah itu ditugaskan selain null? Jika ya, apakah Anda punya contoh?

Julien Chastang
sumber

Jawaban:

116

Voidtelah menjadi konvensi untuk argumen umum yang tidak Anda minati. Tidak ada alasan mengapa Anda harus menggunakan tipe non-instantiable lainnya, seperti System.

Ini juga sering digunakan sebagai Mapnilai contoh (meskipun Collections.newSetFromMapdigunakan Booleansebagai peta tidak harus menerima nullnilai) dan java.security.PrivilegedAction.

Saya menulis sebuah entri weblog pada Voidbeberapa tahun lalu.

Tom Hawtin - tackline
sumber
siapa yang membuat konvensi itu? status dokumen docs.oracle.com/javase/tutorial/java/generics/types.html "Ketik Parameter Penamaan Konvensi Berdasarkan konvensi, ketikkan nama parameter parameter tunggal, huruf besar."
barlop
4
@barlop Ini argumennya bukan nama parameter. Itu adalah tipenya java.lang.Void. / Josh Bloch mempopulerkan konvensi itu, meskipun begitu kau melihatnya, itu adalah pilihan yang jelas.
Tom Hawtin - tackline
2
Entri blog itu sudah mati
mFeinstein
51

Anda dapat membuat instance Void menggunakan refleksi, tetapi mereka tidak berguna untuk apa pun. Void adalah cara untuk menunjukkan metode umum tidak mengembalikan apa pun.

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

mencetak sesuatu seperti

I have a java.lang.Void@75636731
Peter Lawrey
sumber
22
+1 untuk membuat instance kelas yang menurut dokumentasi tidak dapat dibantah. Saya telah melakukan ini juga dan saya setuju bahwa Void yang dipakai tidak berguna.
Luke Woodward
1
Konstruktor <Void> cv = Void.class.getDeclaredConstructor (); cv.setAccessible (true); Batal v = cv.newInstance (); System.out.println (v); //;)
Peter Lawrey
Sebagai latihan, cobalah membuat Kelas baru menggunakan refleksi dan lihat apa yang terjadi.
Peter Lawrey
Saya mendapat java.lang.InstantiationException dari sun.reflect.InstantiationExceptionConstructorAccessorImpl. :(
Luke Woodward
7
Ini adalah implementasi khusus dan dapat berubah sewaktu-waktu. Tidak ada jaminan bahwa kelas memiliki konstruktor no-arg dan bahkan jika itu memiliki satu yang dapat melakukan apa saja (mungkin System.exit(0)). Saya cenderung menulis kelas utilitas dengan konstruktor sebagai private Void() { throw new Error(); }. Beberapa mungkin lebih suka enum tanpa nilai.
Tom Hawtin - tackline
27

Future<Void>bekerja seperti pesona. :)

Alexander Temerev
sumber
6
Ini lebih umum (misalnya, di Jambu) untuk digunakan Future<?>, karena masa depan akan sering memiliki nilai yang sah (dari Voidtipe tidak ) tetapi digunakan dalam konteks yang tidak peduli dengan nilai.
David Phillips
1
CompletableFuture<Void>bekerja seperti pesona juga.
andrybak
19

Mengingat bahwa tidak ada konstruktor publik , saya akan mengatakan itu tidak dapat ditugaskan selain null. Saya hanya menggunakannya sebagai pengganti untuk "Saya tidak perlu menggunakan parameter umum ini," seperti contoh Anda.

Itu juga dapat digunakan dalam refleksi, dari apa yang dikatakan Javadoc -nya :

Kelas Void adalah kelas placeholder uninstantiable untuk memegang referensi ke objek Kelas yang mewakili kekosongan kata kunci Java.

Michael Myers
sumber
Cukup lucu untuk melihat Oracle / Sun menggambarkannya seperti nol adalah turunan dari semua jenis. Bagaimanapun, seperti yang Anda katakan, makna murni dari itu adalah "Saya bisa menulis jenis apa pun di sini karena saya tidak tertarik, jadi saya akan meletakkan Void untuk memastikan orang-orang yang membaca kode saya memahami persis hal itu"
Snicolas
17

Semua kelas wrapper primitif ( Integer, Byte, Boolean, Double, dll) berisi referensi ke kelas primitif yang sesuai dalam static TYPEbidang, misalnya:

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

Voidawalnya dibuat sebagai tempat untuk meletakkan referensi ke voidtipe:

Void.TYPE == void.class

Namun, Anda tidak benar-benar mendapatkan apa pun dengan menggunakan Void.TYPE. Ketika Anda menggunakannya void.class, jauh lebih jelas bahwa Anda melakukan sesuatu dengan voidtipe itu.

Sebagai tambahan, terakhir kali saya mencobanya, BeanShell tidak mengenalinya void.class, jadi Anda harus menggunakannya di Void.TYPEsana.

Luke Woodward
sumber
8
Jadi ada Void.class dan void.class!
Tom Anderson
8

Saat Anda menggunakan pola pengunjung , bisa lebih bersih menggunakan Void daripada Object ketika Anda ingin memastikan bahwa nilai baliknya akan nol

Contoh

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

   OUT visit(Leaf2 leaf);
}

Ketika Anda akan menerapkan pengunjung Anda, Anda dapat secara eksplisit menetapkan OUT menjadi Void sehingga Anda tahu pengunjung Anda akan selalu kembali nol, daripada menggunakan 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;
    }
}
Ronan Quillevere
sumber
5

Sebelum generik, itu dibuat untuk API refleksi, untuk menahan TYPE yang dikembalikan oleh Method.getReturnType () untuk metode batal, sesuai dengan kelas tipe primitif lainnya.

EDIT: Dari JavaDoc of Void: "Kelas Void adalah kelas placeholder yang tidak dapat dibantah untuk menyimpan referensi ke objek Kelas yang mewakili kata kunci Java void". Sebelum ke Generics, saya sadar tidak ada gunanya selain refleksi.

Lawrence Dol
sumber
Saya tidak percaya ini. Saya tidak memiliki JVM 1.4 atau sebelumnya di depan saya sekarang, tetapi saya percaya bahwa Method.getReturnType () selalu mengembalikan void.class untuk metode void.
Luke Woodward
@Pour: Saya mengatakan bahwa sebelum obat generik, satu-satunya penggunaan yang saya ketahui adalah untuk memegang TYPE (seperti pada Void.TYPE), yang digunakan dalam metode Refleksi.getReturnType () untuk metode void.
Lawrence Dol
Entah bagaimana itu tidak kembali Void. Silakan lihat stackoverflow.com/questions/34248693/...
Alireza Fattahi
3

Karena Anda tidak dapat membuat instance Void, Anda dapat menggunakan objek Null Apache commons , jadi

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

di baris pertama, Anda memiliki objek, jadi aNullObject != nulltahan, sedangkan di baris kedua tidak ada referensi, jadi noObjectHere == nulltahan

Untuk menjawab pertanyaan asli poster, penggunaannya adalah untuk membedakan antara "tidak ada" dan "tidak ada", yang merupakan hal yang sama sekali berbeda.

PS: Katakan tidak pada pola objek Null

Mar Bar
sumber
1

Void dibuat untuk membungkus tipe void primitifnya. Setiap tipe primitif memiliki tipe referensi yang sesuai. Void digunakan untuk instantiate kelas generik atau penggunaan metode generik, Argumen penyihir generik yang Anda tidak tertarik. Dan di sini adalah contoh ...

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

di sini, seperti yang Anda lihat, saya tidak ingin apa pun dari server yang saya minta untuk membuat registrasi baru, tetapi public interface AsyncCallback<T> { .... }merupakan antarmuka generik jadi saya memberikan Void karena generik tidak menerima tipe primitif

Adelin
sumber
0

Ini juga biasa digunakan pada callback penyelesaian Async-IO ketika Anda tidak membutuhkan Attachmentobjek. Dalam hal ini Anda tentukan null untuk operasi dan implementasi IO CompletionHandler<Integer,Void>.

eek
sumber
0

Ini mungkin kasus yang jarang tetapi sekali, saya digunakan Voiddi kelas aspek.

Ini adalah aspek yang berjalan setelah metode yang memiliki @Loganotasi, dan mencatat metode kembali dan beberapa info jika jenis metode kembali tidak batal.

 @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
         }
}
Alireza Fattahi
sumber