mengembalikan objek Void

113

Apa cara yang benar untuk mengembalikan sebuah Voidtipe, jika itu bukan primitif? Misalnya. Saat ini saya menggunakan null seperti di bawah ini.

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something
        return null;
    }
}
Robert
sumber
1
Saya menulis penerjemah untuk format file, menggunakan pola interpreter, tetapi beberapa ekspresi tidak memiliki nilai yang dikembalikan
Robert
2
Tidak ada cara untuk membuat instance tipe Void, jadi jika Anda benar-benar harus mengembalikan sesuatu dari tipe itu, null adalah satu-satunya pilihan Anda. Namun, Anda mungkin tidak memerlukan nilai yang dikembalikan untuk apa pun, jadi null sudah cukup.
Jorn
ya, itu logika saya juga - hanya ingin tahu apakah ada cara yang lebih semantik
Robert
1
Saya akan mengkodekannya seperti contoh Anda. Itu pendekatan yang bagus.
David Roussel

Jawaban:

134

Kelas Void adalah kelas tempat penampung yang tidak dapat dibuktikan untuk menyimpan referensi ke objek Kelas yang mewakili kata kunci Java void.

Jadi, salah satu dari berikut ini sudah cukup:

  • parameterisasi dengan Objectdan kembali new Object()ataunull
  • parameterisasi dengan Voiddan kembalinull
  • parameterizing dengan NullObjectmilik Anda

Anda tidak dapat membuat metode ini void, dan yang lainnya mengembalikan sesuatu . Karena sesuatu itu diabaikan, Anda dapat mengembalikan apapun.

Bozho
sumber
2
lalu apa cara yang benar secara umum untuk mencapai tipe pengembalian kosong?
Robert
1
Jika Anda ingin mengembalikan null sebagai batal, Anda perlu memasukkannya dalam beberapa kasus: (Void) null
Patrick Favre
return (Void)null;
Alex R
dapatkah (Void) null dibedakan dari null dengan cara apa pun?
Jeruk
13

Java 8 telah memperkenalkan kelas baru Optional<T>, yang dapat digunakan dalam kasus seperti itu. Untuk menggunakannya, Anda akan sedikit mengubah kode sebagai berikut:

interface B<E>{ Optional<E> method(); }

class A implements B<Void>{

    public Optional<Void> method(){
        // do something
        return Optional.empty();
    }
}

Ini memungkinkan Anda untuk memastikan bahwa Anda selalu mendapatkan nilai pengembalian bukan nol dari metode Anda, bahkan ketika tidak ada yang dikembalikan. Itu sangat kuat ketika digunakan bersama dengan alat yang mendeteksi kapan nullbisa atau tidak bisa dikembalikan, misalnya Eclipse @NonNulldan @Nullableanotasi.

Erick G. Hagstrom
sumber
5
Pendapat saya adalah bahwa ini menuju ke arah yang salah. Lebih baik mengembalikan jenis yang jauh lebih terbatas yang menyampaikan artinya lebih jelas. Memiliki sesuatu yang mengembalikan Optional<Void>tidak diperlukan untuk alasan yang sama dengan yang Anda berikan, Anda selalu mendapatkan Optional<Void>yang kosong sehingga semua metode lain tidak ada gunanya. Ini kebalikan dari mengapa nilai opsional harus digunakan. Anda menggunakannya karena mungkin atau mungkin tidak memiliki nilai. Juga kompilator tidak bisa method()menerapkannya dengan benar. Ini akan gagal di runtime: return Optional.of(null).
steinybot
3

Jika Anda tidak membutuhkan apa pun sebagai tipe Anda, Anda dapat menggunakan void. Ini dapat digunakan untuk mengimplementasikan fungsi, atau tindakan. Anda kemudian dapat melakukan sesuatu seperti ini:

interface Action<T> {
    public T execute();
}

abstract class VoidAction implements Action<Void> {
    public Void execute() {
        executeInternal();
        return null;
    }

    abstract void executeInternal();
}

Atau Anda bisa menghilangkan kelas abstrak, dan melakukan pengembalian null dalam setiap tindakan yang tidak memerlukan nilai pengembalian sendiri.

Anda kemudian dapat menggunakan tindakan seperti ini:

Diberikan metode

private static <T> T executeAction(Action<T> action) {
    return action.execute();
}

Anda bisa menyebutnya seperti

String result = executeAction(new Action<String>() {
    @Override
    public String execute() {
        //code here
        return "Return me!";
    }
});

atau, untuk tindakan void (perhatikan bahwa Anda tidak menetapkan hasilnya untuk apa pun)

executeAction(new VoidAction() {
    @Override
    public void executeInternal() {
        //code here
    }
});
Jorn
sumber
2
bagaimana ini berbeda dari yang sudah saya miliki? itu masih saja mengembalikan nol, seperti yang saya sarankan
Robert
Mengapa Anda harus mengembalikan yang lain? Poin yang ingin saya sampaikan adalah Anda tidak memerlukan nilai pengembalian, jadi tidak masalah apa yang Anda kembalikan. Saya mencoba menjelaskannya dengan suntingan saya.
Jorn
1

Hanya demi itu, tentu saja ada kemungkinan untuk membuat Voidinstance menggunakan refleksi:

interface B<E>{ E method(); }

class A implements B<Void>{

    public Void method(){
        // do something

        try {
            Constructor<Void> voidConstructor = Void.class.getDeclaredConstructor();
            voidConstructor.setAccessible(true);
            return voidConstructor.newInstance();
        } catch (Exception ex) {
            // Rethrow, or return null, or whatever.
        }
    }
}

Anda mungkin tidak akan melakukannya dalam produksi.

kap
sumber
0

Tidak ada tipe generik yang akan memberi tahu kompiler bahwa sebuah metode tidak mengembalikan apa-apa.

Saya percaya konvensi adalah menggunakan Object saat mewarisi sebagai parameter tipe

ATAU

Sebarkan parameter type ke atas dan kemudian biarkan pengguna kelas Anda membuat instance menggunakan Object dan menugaskan objek ke variabel yang diketik menggunakan jenis-wildcard ?:

interface B<E>{ E method(); }

class A<T> implements B<T>{

    public T method(){
        // do something
        return null;
    }
}

A<?> a = new A<Object>();
Christopher Oezbek
sumber
1
apakah ini konvensi untuk menyetel tipe pengembalian menjadi kosong dengan generik - tidak terlihat sangat kosong bagi saya?
Robert
Saya percaya ini adalah cara untuk pergi. Semua pengguna kelas A<?>tidak akan dapat menggunakan nilai yang dikembalikan dari method().
Christopher Oezbek