Java: Kelas Statis?

130

Saya memiliki kelas yang penuh dengan fungsi utilitas. Instantiasi contoh itu tidak masuk akal semantik, tapi saya masih ingin menyebut metodenya. Apa cara terbaik untuk menghadapi ini? Kelas statis? Abstrak?

Nick Heiner
sumber
14
Anda tidak dapat membuat kelas tingkat atas statis by the way ...
Jon

Jawaban:

163

Konstruktor pribadi dan metode statis pada kelas ditandai sebagai final.

David Robles
sumber
19
@matt b: Seperti yang ditunjukkan David Robles dalam jawabannya, Anda tidak perlu membuat kelas menjadi final ... itu tidak dapat disubklasifikasikan karena subkelas tidak akan dapat memanggil konstruktor kelas super karena sifatnya pribadi. Namun ... tidak ada salahnya menjadi eksplisit. Tapi jfyi :-).
Tom
93

Menurut buku hebat "Java Efektif" :

Butir 4: Menegakkan noninstantiability dengan konstruktor pribadi

- Berusaha untuk menegakkan noninstantiability dengan membuat abstrak kelas tidak berfungsi.

- Konstruktor default dihasilkan hanya jika kelas tidak mengandung konstruktor eksplisit, sehingga kelas dapat dibuat tidak dapat dibuktikan dengan menyertakan konstruktor pribadi:

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

Karena konstruktor eksplisit bersifat privat, konstruktor tidak dapat diakses di luar kelas. AssertionError tidak sepenuhnya diperlukan, tetapi menyediakan asuransi jika konstruktor secara tidak sengaja dipanggil dari dalam kelas. Ini menjamin bahwa kelas tidak akan pernah dipakai dalam keadaan apa pun. Ungkapan ini agak berlawanan dengan intuisi, karena konstruktor disediakan secara tegas sehingga tidak dapat dipanggil. Oleh karena itu bijaksana untuk memasukkan komentar, seperti yang ditunjukkan di atas.

Sebagai efek samping, idiom ini juga mencegah kelas menjadi subclass. Semua konstruktor harus memanggil konstruktor superclass, secara eksplisit atau implisit, dan subkelas tidak memiliki konstruktor superclass yang dapat diakses untuk dipanggil.

David Robles
sumber
1
Mengapa Anda memilih AssertionErroratas alternatif lain seperti IllegalStateException, UnsupportedOperationException, dll?
Pacerier
@Pacerier Lihat ini .
bcsb1001
@ bcsb1001, Itu membawa kita ke ini .
Pacerier
21

Kedengarannya seperti Anda memiliki kelas utilitas yang mirip dengan java.lang.Math .
Pendekatannya ada kelas akhir dengan konstruktor pribadi dan metode statis.

Tetapi berhati-hatilah dengan apa yang dilakukan untuk testabilitas, saya sarankan membaca artikel ini.
Metode Statis adalah Kematian untuk Testabilitas

crowne
sumber
Jadi apakah java.lang.Math "kematian untuk testabilitas"?
Pacerier
1
Mungkin menarik untuk melihat bagaimana skornya ketika dijalankan melalui code.google.com/p/testability-explorer
crowne
6

Hanya untuk berenang di hulu, anggota dan kelas statis tidak berpartisipasi dalam OO dan karenanya jahat. Tidak, tidak jahat, tapi serius, saya akan merekomendasikan kelas reguler dengan pola akses tunggal. Dengan cara ini jika Anda perlu mengesampingkan perilaku dalam kasus apa pun di jalan, itu bukan perombakan besar. OO adalah temanmu :-)

$ 0,02 saya

Bennett Dill
sumber
17
Lajang juga dianggap jahat.
Dan Dyer
3
Anda menggunakan konstruktor pribadi untuk mencegah siapa pun membuat instance atau subclass kelas. Lihat jawaban David Robles ': stackoverflow.com/questions/1844355/java-static-class/…
rob
5
tunggal tidak lebih jahat dari injeksi ketergantungan :)
irreputable
12
OO memiliki tempatnya, tetapi ada kalanya itu tidak praktis, atau itu akan menjadi pemborosan sumber daya - misalnya, sesuatu yang sederhana seperti Math.abs (). Tidak ada alasan untuk instantiate objek hanya demi instantiate objek, ketika panggilan metode statis akan melayani Anda dengan baik tanpa OO-overhead. ;)
merampok
2
@rob re OO, saya setuju, Math.Abs ​​mungkin tidak pernah membutuhkan sebuah instance. Ketika saya mendengar "saya memiliki kelas utilitas", saya melihat Math.Avg (), di mana Anda sekarang perlu menambahkan dukungan untuk rata-rata tertimbang. Saya melihat generator Url, param in, url yang perlu di refactored untuk mendukung href, atau hanya url, dll. Untuk alasan ini, memiliki kelas utilitas berbasis OO dapat membayar kembali. Juga, sekarang saya akan menjatuhkan taktik defensif standar OO, pengujian! / Me bebek
Bennett Dill
3

mengomentari argumen "konstruktor pribadi": ayolah, pengembang tidak sebodoh itu; tapi mereka malas. membuat objek lalu memanggil metode statis? tidak akan terjadi.

jangan menghabiskan terlalu banyak waktu untuk memastikan kelas Anda tidak dapat disalahgunakan. memiliki keyakinan untuk kolega Anda. dan selalu ada cara untuk menyalahgunakan kelas Anda tidak peduli bagaimana Anda melindunginya. satu-satunya hal yang tidak dapat disalahgunakan adalah hal yang sama sekali tidak berguna.

tak dapat disangkal
sumber
7
Seseorang yang telah melihat (dalam kode produksi, bukan hanya kode siswa) object.staticMethod Saya pikir Anda melebih-lebihkan kemampuan Joe Random Programmer! :-P
TofuBeer
2
  • Kelas terakhir dan konstruktor pribadi (baik tetapi tidak penting)
  • Metode statis publik
fastcodejava
sumber
1

Tidak ada gunanya mendeklarasikan kelas sebagai static. Cukup deklarasikan metodenya staticdan panggil mereka dari nama kelas seperti biasa, seperti kelas Matematika Java .

Juga, meskipun tidak sepenuhnya membuat konstruktor pribadi, itu ide yang baik untuk melakukannya. Menandai konstruktor pribadi mencegah orang lain membuat instance kelas Anda, lalu memanggil metode statis dari instance tersebut. (Panggilan ini bekerja persis sama di Jawa, mereka hanya menyesatkan dan merusak keterbacaan kode Anda.)

Bill the Lizard
sumber
1
Juga, jangan lupa untuk membuat konstruktor pribadi.
Asaph
@ Asaf: Setuju. Saya menambahkan sedikit pada jawaban saya. Terima kasih.
Bill the Lizard
Jika Anda ingin metode statis dalam kelas dalam, kelas tersebut juga harus statis.
Rui Marques