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?



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.


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

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


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.


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.


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

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.


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


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


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>.


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
         }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.