Katakanlah saya memiliki kelas yang dirancang untuk dipakai. Saya memiliki beberapa metode "pembantu" pribadi di dalam kelas yang tidak memerlukan akses ke anggota kelas mana pun, dan beroperasi hanya berdasarkan argumen mereka, mengembalikan hasilnya.
public class Example {
private Something member;
public double compute() {
double total = 0;
total += computeOne(member);
total += computeMore(member);
return total;
}
private double computeOne(Something arg) { ... }
private double computeMore(Something arg) {... }
}
Apakah ada alasan khusus untuk menentukan computeOne
dan computeMore
sebagai metode statis - atau alasan tertentu untuk tidak melakukannya?
Tentunya lebih mudah untuk membiarkan mereka sebagai non-statis, meskipun mereka bisa statis tanpa menimbulkan masalah.
java
static
methods
static-methods
avalys
sumber
sumber
Jawaban:
Saya lebih suka metode pembantu seperti itu
private static
; yang akan menjelaskan kepada pembaca bahwa mereka tidak akan mengubah keadaan objek. IDE saya juga akan menunjukkan panggilan ke metode statis dalam huruf miring, jadi saya akan tahu metode ini statis tanpa melihat tanda tangan.sumber
protected static
yang membuatnya mudah diuji di kelas uji dalam paket yang sama.static
(jika kami hanya menginginkannya untuk pengujian).Mungkin menghasilkan bytecode sedikit lebih kecil, karena metode statis tidak akan mendapatkan akses
this
. Saya tidak berpikir itu membuat perbedaan dalam kecepatan (dan jika ya, mungkin akan terlalu kecil untuk membuat perbedaan secara keseluruhan).Saya akan membuatnya statis, karena saya biasanya melakukannya jika memungkinkan. Tapi itu hanya aku.
EDIT: Jawaban ini terus diturunkan, mungkin karena pernyataan tidak berdasar tentang ukuran bytecode. Jadi saya benar-benar akan menjalankan tes.
Bytecode (diambil dengan
javap -c -private TestBytecodeSize
):Meminta metode statis membutuhkan dua bytecode (byteops?):
iconst_0
(Untuk argumen) daninvokestatic
.Meminta metode non-statis membutuhkan tiga:
aload_1
(untukTestBytecodeSize
objek, saya kira),iconst_0
(untuk argumen), daninvokespecial
. (Perhatikan bahwa jika ini bukan metode pribadi, itu akan menjadiinvokevirtual
bukaninvokespecial
; lihat JLS §7.7 Metode Memohon .)Sekarang, seperti yang saya katakan, saya tidak berharap akan ada perbedaan besar dalam kinerja antara keduanya, selain dari fakta yang
invokestatic
membutuhkan satu bytecode lebih sedikit.invokestatic
daninvokespecial
keduanya harus sedikit lebih cepat daripadainvokevirtual
, karena keduanya menggunakan pengikatan statis alih-alih dinamis, tapi saya tidak tahu apakah keduanya lebih cepat dari yang lain. Saya juga tidak dapat menemukan referensi yang bagus. Yang paling dekat yang bisa saya temukan adalah artikel JavaWorld 1997 ini , yang pada dasarnya menyatakan kembali apa yang saya katakan:Tetapi banyak hal telah berubah sejak 1997.
Jadi sebagai kesimpulan ... Saya kira saya masih tetap dengan apa yang saya katakan sebelumnya. Kecepatan tidak boleh menjadi alasan untuk memilih satu dari yang lain, karena itu akan menjadi optimasi mikro terbaik.
sumber
Preferensi pribadi saya adalah menyatakannya statis, karena ini adalah tanda yang jelas bahwa mereka tidak memiliki kewarganegaraan.
sumber
Jawabannya adalah, tergantung.
Jika anggota adalah variabel instan untuk objek yang Anda hadapi, lalu mengapa harus memberikannya sebagai parameter?
Misalnya:
sumber
Salah satu alasan Anda mungkin ingin mendeklarasikan metode pembantu statis adalah jika Anda perlu memanggil mereka di konstruktor kelas "sebelum"
this
atausuper
. Sebagai contoh:Ini sedikit contoh yang dibuat-buat tetapi jelas
recoverInt
tidak bisa menjadi metode contoh dalam kasus ini.sumber
Saya tidak bisa memikirkan keuntungan yang jelas untuk metode statis pribadi. Yang sedang berkata, tidak ada keuntungan khusus untuk membuat mereka tidak statis juga. Ini terutama masalah presentasi: Anda mungkin ingin membuatnya statis untuk menggarisbawahi fakta bahwa mereka tidak mengubah objek.
Untuk metode dengan hak akses yang berbeda, saya pikir ada dua argumen utama:
Selain itu, perbedaannya cukup kecil, dan saya sangat ragu bahwa tambahan pointer ini diteruskan ke metode contoh membuat perbedaan yang signifikan.
sumber
Jawaban yang Benar adalah:
metode apa pun yang tidak mengambil informasi apa pun dari suatu bidang, dan tidak memasukkan informasi apa pun ke dalam bidang, tidak harus menjadi metode contoh. Metode apa pun yang tidak menggunakan atau mengubah bidang apa pun di kelas atau objeknya mungkin juga merupakan metode statis.
sumber
Iya.
Dengan menjadikannya sebagai metode instan, Anda mengizinkan diri Anda untuk memberikan implementasi yang berbeda nanti.
Mungkin terdengar konyol (dan sebenarnya jika metode itu hanya digunakan oleh Anda dalam program 50 baris) tetapi dalam aplikasi yang lebih besar, atau di perpustakaan yang digunakan oleh orang lain, Anda dapat memutuskan untuk memilih implementasi yang lebih baik, tetapi jangan ingin memecahkan kode yang ada.
Jadi, Anda membuat subkelas dan mengembalikannya di versi baru, dan karena metode tersebut dinyatakan sebagai metode instan, Anda hanya membiarkan polimorfisme melakukan tugasnya.
Selain itu, Anda dapat mengambil manfaat dari menjadikan konstruktor sebagai pribadi dan menyediakan metode pabrik statis untuk alasan yang sama.
Jadi, rekomendasi saya adalah menyimpannya sebagai metode instan, dan menghindari statis jika memungkinkan.
Manfaatkan dinamika yang disediakan bahasa.
Lihat di sini untuk video yang agak terkait: Cara mendesain API yang baik dan mengapa itu penting
Meskipun tidak terkait langsung dengan diskusi metode "static vs instance", itu menyentuh beberapa poin menarik dalam desain API.
sumber
Salah satu masalah tentang memiliki metode statis adalah bahwa hal itu dapat membuat objek lebih sulit digunakan dalam pengujian unit . Mockito tidak dapat membuat tiruan untuk metode statis dan Anda tidak bisa membuat implementasi subclass dari metode ini.
sumber
Jika metode ini pada dasarnya hanya sebuah subrutin yang tidak akan pernah dapat menggunakan informasi status sebelumnya, nyatakan itu statis.
Ini memungkinkannya untuk digunakan dalam metode statis lain atau inisialisasi kelas, yaitu:
sumber
Pertanyaan statis / non-statis turun ke "apakah saya benar-benar perlu menggunakan objek dari kelas ini"?
Jadi, apakah Anda melewati objek di antara metode yang berbeda? Apakah objek berisi informasi yang berguna di luar konteks metode statis? Apakah ada alasan untuk tidak mendefinisikan metode kedua cara jika Anda akan menggunakan keduanya?
Jika Anda berada dalam dilema ini, menurut saya Anda memiliki semua data yang diperlukan untuk metode yang mengambang di kode Anda di luar objek. Apa ini yang kau inginkan? Apakah akan lebih mudah untuk selalu mengumpulkan data itu menjadi objek setiap kali? Anda mungkin ambivalen tentang komitmen terhadap model tunggal. Jika Anda dapat melakukan semuanya dengan satu cara, pilih yang statis atau non-statis dan ikuti saja.
sumber
Preferensi saya dalam kasus seperti ini adalah membuat
computeOne
dancomputeMore
metode statis. Alasannya: enkapsulasi. Semakin sedikit kode yang memiliki akses ke implementasi kelas Anda, semakin baik.Dalam contoh yang Anda berikan, Anda menyatakan bahwa
computeOne
dancomputeMore
tidak perlu mengakses bagian dalam kelas, jadi mengapa memberikan kesempatan bagi pengelola kelas untuk ikut campur dengan bagian dalam.sumber
Saya ingin mengklarifikasi beberapa hal yang dikatakan poster lain sebagai informasi yang salah.
Pertama karena metode ini bersifat pribadi bahkan jika Anda menyatakannya statis, Anda tidak akan dapat mengaksesnya di luar kelas ini. Kedua mereka bersifat pribadi sehingga Anda bahkan tidak bisa menimpa dalam subkelas sehingga statis atau non-statis tidak ada bedanya. Ketiga, metode pribadi non-statis dapat dipanggil dari konstruktor kelas juga, itu tidak perlu statis.
Sekarang datang ke pertanyaan Anda jika metode pembantu pribadi harus didefinisikan sebagai statis atau non-statis. Saya akan pergi dengan jawaban Steve sebagai menandai metode privat statis menunjukkan bahwa metode ini stateless karena saya juga mengikuti aturan ini ketika saya kode.
sumber
Dari pengalaman saya akan menyatakan bahwa metode pribadi seperti itu cenderung sangat universal dan dapat digunakan kembali.
Saya pikir hal pertama yang harus dilakukan adalah mengajukan pertanyaan apakah metode ini mungkin berguna di luar konteks kelas saat ini. Jika demikian, saya akan melakukan apa yang Semua orang sarankan dan ekstrak metode ini sebagai statis ke beberapa kelas utilitas di mana seseorang mudah-mudahan memeriksa sebelum menerapkan metode baru melakukan hal yang persis sama.
Penggunaan metode pribadi yang umum seperti itu adalah sumber dari sebagian besar duplikasi kode dalam proyek karena setiap pengembang secara mandiri menemukan kembali mereka hanya di tempat yang ia perlukan untuk menggunakannya. Jadi sentralisasi metode semacam itu adalah cara untuk maju.
sumber
Lebih khusus dengan contoh yang Anda berikan, tampaknya bahwa tujuan mendefinisikan metode ini lebih untuk kejelasan kode ketika Anda sedang membaca daripada untuk fungsi (mereka yang didefinisikan sebagai pribadi). Dalam hal itu, pergi dengan statis benar-benar tidak berguna bagi Anda, karena tujuan statis adalah untuk mengekspos fungsionalitas kelas.
sumber
Salah satu alasannya adalah, semua yang dianggap sama, panggilan metode statis harus lebih cepat. Metode statis tidak boleh virtual, dan jangan mengambil referensi implisit ini.
sumber
Seperti yang dikatakan banyak orang, jadikan itu statis ! Berikut adalah aturan praktis yang saya ikuti: Jika Anda berpikir metode ini hanya fungsi matematika yaitu stateless, tidak melibatkan variabel instan (=> tidak ada vars warna biru [dalam gerhana] dalam metode), dan hasil dari metode akan sama untuk jumlah panggilan 'n' (dengan parameter yang sama, tentu saja), lalu tandai metode itu sebagai STATIC.
Dan jika Anda berpikir bahwa metode ini akan berguna untuk kelas lain maka pindahkan ke kelas Util jika tidak, letakkan metode ini sebagai privat di dalam sameclass. (meminimalkan aksesibilitas)
sumber
Off-Topic: Saya akan menyimpan metode helper di kelas utilitas mandiri / helper dengan hanya metode statis di dalamnya.
Masalahnya dengan memiliki metode penolong pada titik penggunaan (baca 'kelas yang sama') adalah bahwa seseorang di telepon mungkin hanya memilih untuk memposting metode penolong mereka yang tidak terkait di tempat yang sama
sumber
Keuntungan dari metode statis privat adalah bahwa mereka dapat digunakan kembali nanti jika Anda perlu menginisialisasi ulang variabel kelas.
sumber
Tanpa pengubah statis, Anda tidak dapat mengetahui bahwa metode ini adalah stateless tanpa analisis tambahan yang dapat dengan mudah dilakukan ketika Anda (kembali) menulis metode tersebut.
Kemudian pengubah "statis" dapat memberi Anda gagasan tentang refactoring selain hal-hal lain yang mungkin dianggap tidak berguna oleh orang lain. Misalnya memindahkan metode ke beberapa kelas Utilitas atau mengubahnya menjadi metode anggota ..
sumber
Saya akan menyatakan mereka sebagai statis untuk menandai mereka sebagai stateless.
Java tidak memiliki mekanisme yang lebih baik untuk operasi kecil yang tidak diekspor, jadi saya pikir privat statis dapat diterima.
sumber