Saya seorang programmer Java yang baru dalam dunia korporat. Baru-baru ini saya telah mengembangkan aplikasi menggunakan Groovy dan Java. Semua melalui kode yang saya tulis menggunakan statika yang cukup baik. Saya diminta oleh banyak teknis senior untuk mengurangi jumlah statika yang digunakan. Saya sudah googled tentang hal yang sama, dan saya menemukan bahwa banyak programmer cukup menentang menggunakan variabel statis.
Saya menemukan variabel statis lebih nyaman digunakan. Dan saya menganggap bahwa mereka juga efisien (tolong perbaiki saya jika saya salah), karena jika saya harus membuat 10.000 panggilan ke suatu fungsi dalam suatu kelas, saya akan senang untuk membuat metode ini statis dan langsung menggunakan metode Class.methodCall()
itu daripada menggunakannya mengacaukan memori dengan 10.000 instance kelas, kan?
Selain itu statika mengurangi saling ketergantungan pada bagian lain dari kode. Mereka dapat bertindak sebagai pemegang negara yang sempurna. Menambah ini saya menemukan bahwa statika banyak diimplementasikan dalam beberapa bahasa seperti Smalltalk dan Scala . Jadi mengapa penindasan terhadap statika ini lazim di kalangan pemrogram (terutama di dunia Jawa)?
PS: tolong perbaiki saya kalau anggapan saya tentang statika salah.
Jawaban:
Variabel statis mewakili keadaan global. Itu sulit untuk dipikirkan dan sulit untuk diuji: jika saya membuat instance baru dari sebuah objek, saya bisa beralasan tentang status barunya dalam pengujian. Jika saya menggunakan kode yang menggunakan variabel statis, bisa dalam keadaan apa pun - dan apa pun bisa memodifikasinya.
Saya bisa berjalan cukup lama, tetapi konsep yang lebih besar untuk dipikirkan adalah semakin sempit ruang lingkup sesuatu, semakin mudah untuk dipikirkan. Kami pandai memikirkan hal-hal kecil, tetapi sulit untuk beralasan tentang keadaan sistem sejuta baris jika tidak ada modularitas. Omong-omong, ini berlaku untuk segala macam hal - bukan hanya variabel statis.
sumber
Ini tidak terlalu berorientasi objek: Salah satu alasan statika dapat dianggap "jahat" oleh beberapa orang adalah mereka bertentangan dengan paradigma berorientasi objek . Secara khusus, itu melanggar prinsip bahwa data dienkapsulasi dalam objek (yang dapat diperluas, menyembunyikan informasi, dll). Statika, dalam cara Anda menggambarkan menggunakannya, pada dasarnya menggunakannya sebagai variabel global untuk menghindari berurusan dengan masalah seperti ruang lingkup. Namun, variabel global adalah salah satu karakteristik mendefinisikan paradigma pemrograman prosedural atau imperatif, bukan karakteristik kode berorientasi objek "baik". Ini bukan untuk mengatakan paradigma prosedural itu buruk, tetapi saya mendapat kesan atasan Anda mengharapkan Anda untuk menulis "kode berorientasi objek yang baik" dan Anda benar-benar ingin menulis "
Ada banyak gotcha di Jawa ketika Anda mulai menggunakan statika yang tidak selalu langsung terlihat jelas. Misalnya, jika Anda memiliki dua salinan dari program Anda yang berjalan di VM yang sama, apakah mereka akan mengubah nilai variabel statis dan mengacaukan keadaan satu sama lain? Atau apa yang terjadi ketika Anda memperluas kelas, dapatkah Anda mengganti anggota statis? Apakah VM Anda kehabisan memori karena Anda memiliki jumlah statika yang gila dan bahwa memori tidak dapat direklamasi untuk objek instance lain yang diperlukan?
Obyek Seumur Hidup: Selain itu, statika memiliki masa hidup yang cocok dengan seluruh runtime program. Ini berarti, bahkan setelah Anda selesai menggunakan kelas Anda, memori dari semua variabel statis tidak dapat dikumpulkan sampah. Jika, misalnya, sebagai gantinya, Anda membuat variabel Anda non-statis, dan pada fungsi utama Anda (), Anda membuat instance tunggal dari kelas Anda, dan kemudian meminta kelas Anda untuk menjalankan fungsi tertentu 10.000 kali, setelah 10.000 panggilan dilakukan , dan Anda menghapus referensi Anda ke satu contoh, semua variabel statis Anda bisa menjadi sampah yang dikumpulkan dan digunakan kembali.
Mencegah penggunaan ulang tertentu: Selain itu, metode statis tidak dapat digunakan untuk mengimplementasikan antarmuka, sehingga metode statis dapat mencegah fitur berorientasi objek tertentu agar tidak dapat digunakan.
Pilihan lain: Jika efisiensi adalah perhatian utama Anda, mungkin ada cara lain yang lebih baik untuk memecahkan masalah kecepatan daripada hanya mempertimbangkan keuntungan doa biasanya lebih cepat daripada penciptaan. Pertimbangkan apakah pengubah transien atau volatil diperlukan di mana saja. Untuk mempertahankan kemampuan yang akan diuraikan, suatu metode dapat ditandai sebagai final alih-alih statis. Parameter metode dan variabel lainnya dapat ditandai sebagai final untuk mengizinkan optimiaisasi kompiler tertentu berdasarkan pada asumsi tentang apa yang dapat mengubah variabel-variabel tersebut. Objek instance dapat digunakan kembali beberapa kali daripada membuat instance baru setiap kali. Mungkin ada saklar optimisasi kompiler yang harus dihidupkan untuk aplikasi secara umum. Mungkin, desain harus diatur sehingga 10.000 berjalan dapat multi-threaded dan memanfaatkan core multi-prosesor. Jika portablity tidak
Jika karena alasan tertentu Anda tidak ingin banyak salinan dari suatu objek, pola desain tunggal, memiliki kelebihan dibandingkan objek statis, seperti keamanan ulir (menganggap singleton Anda dikodekan dengan baik), memungkinkan inisialisasi malas, menjamin objek telah diinisialisasi dengan benar ketika digunakan, sub-klasifikasi, keuntungan dalam pengujian dan refactoring kode Anda, belum lagi, jika pada titik tertentu Anda berubah pikiran tentang hanya menginginkan satu instance objek, JAUH lebih mudah untuk menghapus kode untuk mencegah duplikat instance daripada untuk refactor semua kode variabel statis Anda untuk menggunakan variabel instance. Saya harus melakukan itu sebelumnya, itu tidak menyenangkan, dan Anda akhirnya harus mengedit lebih banyak kelas, yang meningkatkan risiko memperkenalkan bug baru ... jauh lebih baik untuk mengatur hal-hal "benar" pertama kali, bahkan jika itu sepertinya memiliki kelemahan. Untuk saya, pengerjaan ulang yang diperlukan jika Anda memutuskan jalan yang Anda butuhkan beberapa salinan sesuatu mungkin merupakan salah satu alasan yang paling menarik untuk menggunakan statika sesering mungkin. Dan dengan demikian saya juga tidak setuju dengan pernyataan Anda bahwa statika mengurangi inter-dependensi, saya pikir Anda akan berakhir dengan kode yang lebih digabungkan jika Anda memiliki banyak statika yang dapat langsung diakses, daripada objek yang "tahu bagaimana melakukan sesuatu "pada dirinya sendiri.
sumber
synchronized
metode), itu tidak berarti kode panggilan bebas dari kondisi ras sehubungan dengan negara singleton.Object Lifetime
, adalah satu hal yang sangat penting yang @jessica sebutkan.Kejahatan adalah istilah subyektif.
Anda tidak mengendalikan statika dalam hal penciptaan dan penghancuran. Mereka hidup atas perintah program bongkar muat.
Karena statika hidup dalam satu ruang, semua utas yang ingin menggunakannya harus melalui kontrol akses yang harus Anda kelola. Ini berarti bahwa program lebih digabungkan dan perubahan ini lebih sulit untuk dibayangkan dan dikelola (seperti kata J Skeet). Ini mengarah pada masalah mengisolasi dampak perubahan dan dengan demikian mempengaruhi bagaimana pengujian dikelola.
Ini adalah dua masalah utama yang saya miliki dengan mereka.
sumber
Tidak. Negara-negara global tidak jahat pada dasarnya. Tetapi kami harus melihat kode Anda untuk melihat apakah Anda menggunakannya dengan benar. Sangat mungkin bahwa seorang pemula melecehkan negara-negara global; sama seperti dia akan menyalahgunakan setiap fitur bahasa.
Negara-negara global adalah kebutuhan mutlak. Kita tidak bisa menghindari negara global. Kita tidak dapat menghindari alasan tentang negara global. - Jika kita ingin memahami semantik aplikasi kita.
Orang-orang yang berusaha untuk menyingkirkan negara-negara global demi hal itu, pasti berakhir dengan sistem yang jauh lebih kompleks - dan negara-negara global masih ada di sana, secara cerdik / bodoh menyamar di bawah banyak lapisan tipuan; dan kita masih harus bernalar tentang negara-negara global, setelah membuka semua tipuan.
Seperti orang-orang Spring yang dengan boros menyatakan negara global dalam xml dan berpikir entah bagaimana itu lebih unggul.
@ Jon Skeet
if I create a new instance of an object
sekarang Anda memiliki dua hal yang perlu dipikirkan - keadaan dalam objek, dan keadaan lingkungan yang menampung objek.sumber
Ada 2 masalah utama dengan variabel statis:
sumber
Jika Anda menggunakan kata kunci 'statis' tanpa kata kunci 'final', ini harus menjadi sinyal untuk mempertimbangkan dengan cermat desain Anda. Bahkan kehadiran 'final' bukanlah jalan bebas, karena objek final statis yang dapat berubah bisa sama berbahayanya.
Saya akan memperkirakan sekitar 85% dari waktu saya melihat 'statis' tanpa 'final', itu SALAH. Seringkali, saya akan menemukan solusi aneh untuk menutupi atau menyembunyikan masalah ini.
Tolong jangan membuat mutables statis. Terutama Koleksi. Secara umum, Koleksi harus diinisialisasi ketika objek yang berisi diinisialisasi dan harus dirancang sehingga mereka diatur ulang atau dilupakan ketika objek yang mengandung mereka dilupakan.
Menggunakan statika dapat membuat bug yang sangat halus yang akan menyebabkan hari-hari kesakitan para insinyur. Saya tahu, karena saya telah membuat dan memburu bug ini.
Jika Anda ingin lebih detail, baca terus ...
Kenapa Tidak Menggunakan Statika?
Ada banyak masalah dengan statika, termasuk penulisan dan pelaksanaan tes, serta bug halus yang tidak segera terlihat.
Kode yang bergantung pada objek statis tidak dapat dengan mudah diuji unit, dan statika tidak dapat dengan mudah diejek (biasanya).
Jika Anda menggunakan statika, tidak mungkin untuk menukar implementasi kelas keluar untuk menguji komponen tingkat yang lebih tinggi. Misalnya, bayangkan CustomerDAO statis yang mengembalikan objek Pelanggan yang dimuatnya dari database. Sekarang saya memiliki CustomerFilter kelas, yang perlu mengakses beberapa objek Pelanggan. Jika CustomerDAO statis, saya tidak bisa menulis tes untuk CustomerFilter tanpa terlebih dahulu menginisialisasi database saya dan mengisi informasi yang berguna.
Dan populasi basis data dan inisialisasi membutuhkan waktu lama. Dan dalam pengalaman saya, kerangka inisialisasi DB Anda akan berubah seiring waktu, yang berarti data akan berubah, dan tes mungkin rusak. IE, bayangkan Pelanggan 1 dulu VIP, tetapi kerangka inisialisasi DB berubah, dan sekarang Pelanggan 1 tidak lagi VIP, tetapi tes Anda sulit untuk memuat Pelanggan 1 ...
Pendekatan yang lebih baik adalah dengan instantiate CustomerDAO, dan meneruskannya ke CustomerFilter ketika dibangun. (Pendekatan yang lebih baik lagi adalah dengan menggunakan Spring atau kerangka kerja Inversion of Control lainnya.
Setelah Anda melakukan ini, Anda dapat dengan cepat mengejek atau mematikan DAO alternatif di CustomerFilterTest Anda, yang memungkinkan Anda untuk memiliki kontrol lebih besar atas tes,
Tanpa DAO statis, pengujian akan lebih cepat (tanpa inisialisasi db) dan lebih dapat diandalkan (karena tidak akan gagal ketika kode inisialisasi db berubah). Misalnya, dalam hal ini memastikan Pelanggan 1 adalah dan akan selalu menjadi VIP, sejauh menyangkut pengujian.
Melaksanakan Tes
Statika menyebabkan masalah nyata ketika menjalankan suite unit test bersama (misalnya, dengan server Integrasi Berkelanjutan Anda). Bayangkan peta statis objek Socket jaringan yang tetap terbuka dari satu pengujian ke pengujian lainnya. Tes pertama mungkin membuka Socket pada port 8080, tetapi Anda lupa untuk menghapus Peta saat tes dihancurkan. Sekarang ketika tes kedua diluncurkan, kemungkinan akan macet ketika mencoba membuat Socket baru untuk port 8080, karena port tersebut masih ditempati. Bayangkan juga bahwa referensi Socket di Koleksi statis Anda tidak dihapus, dan (dengan pengecualian WeakHashMap) tidak pernah memenuhi syarat untuk menjadi sampah yang dikumpulkan, menyebabkan kebocoran memori.
Ini adalah contoh yang terlalu umum, tetapi dalam sistem besar, masalah ini terjadi SELAMA WAKTU. Orang-orang tidak memikirkan pengujian unit yang memulai dan menghentikan perangkat lunak mereka berulang kali dalam JVM yang sama, tetapi ini adalah tes yang bagus untuk desain perangkat lunak Anda, dan jika Anda memiliki aspirasi terhadap ketersediaan tinggi, itu adalah sesuatu yang perlu Anda waspadai.
Masalah-masalah ini sering muncul dengan objek kerangka kerja, misalnya, akses DB Anda, caching, pesan, dan lapisan logging. Jika Anda menggunakan Java EE atau beberapa kerangka kerja terbaik, mereka mungkin mengelola banyak hal ini untuk Anda, tetapi jika seperti saya Anda berurusan dengan sistem warisan, Anda mungkin memiliki banyak kerangka kerja khusus untuk mengakses lapisan ini.
Jika konfigurasi sistem yang berlaku untuk komponen kerangka ini berubah di antara pengujian unit, dan kerangka kerja pengujian unit tidak meruntuhkan dan membangun kembali komponen, perubahan ini tidak dapat berlaku, dan ketika tes bergantung pada perubahan itu, mereka akan gagal .
Bahkan komponen non-kerangka kerja tunduk pada masalah ini. Bayangkan sebuah peta statis yang disebut OpenOrders. Anda menulis satu tes yang menciptakan beberapa pesanan terbuka, dan memeriksa untuk memastikan semuanya dalam kondisi yang benar, kemudian tes berakhir. Pengembang lain menulis tes kedua yang menempatkan pesanan yang dibutuhkan ke dalam peta OpenOrders, lalu menegaskan jumlah pesanan yang akurat. Jalankan satu per satu, kedua tes ini akan lulus, tetapi ketika dijalankan bersama dalam sebuah suite, keduanya akan gagal.
Lebih buruk lagi, kegagalan mungkin didasarkan pada urutan di mana tes dijalankan.
Dalam hal ini, dengan menghindari statika, Anda menghindari risiko data yang bertahan di seluruh contoh uji, memastikan keandalan tes yang lebih baik.
Bug Halus
Jika Anda bekerja di lingkungan dengan ketersediaan tinggi, atau di mana pun thread dapat dimulai dan dihentikan, masalah yang sama yang disebutkan di atas dengan unit test suites dapat berlaku ketika kode Anda juga berjalan pada produksi.
Saat berurusan dengan utas, daripada menggunakan objek statis untuk menyimpan data, lebih baik menggunakan objek yang diinisialisasi selama fase startup utas. Dengan cara ini, setiap kali utas dimulai, instance objek baru (dengan konfigurasi yang berpotensi baru) dibuat, dan Anda menghindari data dari satu instance thread yang berdarah hingga instance berikutnya.
Ketika sebuah utas mati, objek statis tidak dapat direset atau sampah dikumpulkan. Bayangkan Anda memiliki utas yang disebut "EmailCustomers", dan ketika mulai itu mengisi kumpulan String statis dengan daftar alamat email, kemudian mulai mengirim email masing-masing alamat. Katakanlah utasnya terputus atau dibatalkan, jadi kerangka kerja ketersediaan tinggi Anda memulai ulang utas. Kemudian ketika utas dimulai, ia memuat kembali daftar pelanggan. Tetapi karena koleksinya statis, ia mungkin mempertahankan daftar alamat email dari koleksi sebelumnya. Sekarang beberapa pelanggan mungkin mendapatkan email rangkap.
An Aside: Final Statis
Penggunaan "final statis" secara efektif setara dengan Java dari definisi C #, meskipun ada perbedaan implementasi teknis. AC / C ++ #define diganti dari kode oleh pra-prosesor, sebelum dikompilasi. Java "static final" akan berakhir dengan memori yang tersimpan di stack. Dengan cara itu, ini lebih mirip dengan variabel "static const" di C ++ daripada ke #define.
Ringkasan
Saya harap ini membantu menjelaskan beberapa alasan dasar mengapa statika bermasalah. Jika Anda menggunakan kerangka kerja Java modern seperti Java EE atau Spring, dll, Anda mungkin tidak menemukan banyak dari situasi ini, tetapi jika Anda bekerja dengan tubuh besar kode warisan, mereka bisa menjadi jauh lebih sering.
sumber
Karena tidak ada * yang menyebutkannya: concurrency. Variabel statis dapat mengejutkan Anda jika Anda memiliki beberapa utas membaca dan menulis ke variabel statis. Ini biasa terjadi pada aplikasi web (mis., ASP.NET) dan dapat menyebabkan beberapa bug yang agak menjengkelkan. Misalnya, jika Anda memiliki variabel statis yang diperbarui oleh halaman, dan halaman tersebut diminta oleh dua orang pada "waktu yang hampir bersamaan", satu pengguna mungkin mendapatkan hasil yang diharapkan oleh pengguna lain, atau lebih buruk.
Saya harap Anda siap menggunakan kunci dan berurusan dengan pertengkaran.
* Sebenarnya, Preha Sangha menyebutkannya.
sumber
Meringkas beberapa Keuntungan dasar & Kerugian menggunakan metode statis di Jawa:
Keuntungan:
Kekurangan:
sumber
Anda harus menyeimbangkan kebutuhan untuk merangkum data menjadi objek dengan keadaan, dibandingkan kebutuhan hanya menghitung hasil fungsi pada beberapa data.
Begitu juga enkapsulasi. Dalam aplikasi besar, statika cenderung menghasilkan kode spageti dan tidak mudah memungkinkan refactoring atau pengujian.
Jawaban lain juga memberikan alasan yang bagus untuk tidak menggunakan statika secara berlebihan.
sumber
Variabel statis umumnya dianggap buruk karena mereka mewakili negara global dan karenanya jauh lebih sulit untuk dipikirkan. Secara khusus, mereka mematahkan asumsi pemrograman berorientasi objek. Dalam pemrograman berorientasi objek, setiap objek memiliki statusnya sendiri, diwakili oleh variabel instance (non-statis). Variabel statis mewakili keadaan lintas instance yang jauh lebih sulit untuk diuji unit. Ini terutama karena lebih sulit untuk mengisolasi perubahan pada variabel statis ke tes tunggal.
Yang sedang berkata, penting untuk membuat perbedaan antara variabel statis reguler (umumnya dianggap buruk), dan variabel statis akhir (konstanta AKA; tidak begitu buruk).
sumber
Menurut saya ini hampir tidak pernah tentang kinerja, ini tentang desain. Saya tidak menganggap penggunaan metode statis yang salah sebagai apposed penggunaan variabel statis (tapi saya kira Anda benar-benar berbicara tentang panggilan metode).
Ini hanya tentang bagaimana mengisolasi logika dan memberinya tempat yang baik. Terkadang itu dibenarkan menggunakan metode statis yang
java.lang.Math
merupakan contoh yang baik. Saya pikir ketika Anda menyebutkan sebagian besar kelas AndaXxxUtil
atauXxxhelper
Anda sebaiknya mempertimbangkan kembali desain Anda.sumber
Saya baru saja merangkum beberapa poin yang dibuat dalam jawaban. Jika Anda menemukan sesuatu yang salah, silakan memperbaikinya.
Penskalaan: Kami memiliki tepat satu contoh variabel statis per JVM. Misalkan kita sedang mengembangkan sistem manajemen perpustakaan dan kami memutuskan untuk menempatkan nama buku variabel statis karena hanya ada satu per buku. Tetapi jika sistem tumbuh dan kami menggunakan beberapa JVM maka kami tidak punya cara untuk mencari tahu buku mana yang sedang kami tangani?
Thread-Safety: Baik variabel instan dan variabel statis perlu dikendalikan ketika digunakan di lingkungan multi-ulir. Tetapi dalam kasus variabel instan tidak perlu perlindungan kecuali itu dibagi secara eksplisit antara thread tetapi dalam kasus variabel statis selalu dibagi oleh semua thread dalam proses.
Pengujian: Meskipun desain yang dapat diuji tidak sama dengan desain yang baik tetapi kami jarang akan mengamati desain yang baik yang tidak dapat diuji. Karena variabel statis mewakili keadaan global dan akan sangat sulit untuk mengujinya.
Penalaran tentang keadaan: Jika saya membuat instance baru dari sebuah kelas maka kita dapat alasan tentang keadaan instance ini tetapi jika ia memiliki variabel statis maka bisa dalam keadaan apa pun. Mengapa? Karena ada kemungkinan variabel statis telah dimodifikasi oleh beberapa instance yang berbeda karena variabel statis dibagikan di seluruh instance.
Serialisasi: Serialisasi juga tidak berfungsi dengan baik.
Penciptaan dan penghancuran: Penciptaan dan penghancuran variabel statis tidak dapat dikontrol. Biasanya mereka dibuat dan dihancurkan pada waktu pemuatan dan pembongkaran program. Ini berarti mereka buruk untuk manajemen memori dan juga menambah waktu inisialisasi saat start up.
Tetapi bagaimana jika kita benar-benar membutuhkannya?
Tetapi kadang-kadang kita mungkin benar-benar membutuhkannya. Jika kita benar-benar merasakan perlunya banyak variabel statis yang dibagikan di seluruh aplikasi maka salah satu opsi adalah menggunakan pola Desain Singleton yang akan memiliki semua variabel ini. Atau kita dapat membuat beberapa objek yang akan memiliki variabel statis ini dan dapat diedarkan.
Juga jika variabel statis ditandai final, itu menjadi konstanta dan nilai yang diberikan setelah itu tidak dapat diubah. Itu berarti akan menyelamatkan kita dari semua masalah yang kita hadapi karena sifatnya yang berubah-ubah.
sumber
Menurut saya Anda bertanya tentang variabel statis tetapi Anda juga menunjukkan metode statis dalam contoh Anda.
Variabel statis tidak jahat - mereka memiliki adopsi sebagai variabel global seperti konstanta dalam banyak kasus dikombinasikan dengan pengubah akhir, tetapi seperti dikatakan tidak terlalu sering menggunakannya.
Metode statis alias metode utilitas. Biasanya bukan praktik buruk untuk menggunakannya, tetapi kekhawatiran utama adalah bahwa mereka dapat menghalangi pengujian.
Sebagai contoh proyek java yang hebat yang menggunakan banyak statika dan melakukannya dengan cara yang benar, silakan lihat Play! framework . Ada juga diskusi tentang hal itu di SO.
Variabel / metode statis dikombinasikan dengan impor statis juga banyak digunakan di perpustakaan yang memfasilitasi pemrograman deklaratif di java seperti: membuatnya mudah atau Hamcrest . Itu tidak akan mungkin terjadi tanpa banyak variabel dan metode statis.
Jadi variabel statis (dan metode) bagus tetapi gunakan dengan bijak!
sumber
Variabel statis yang paling penting menciptakan masalah dengan keamanan data (setiap kali diubah, siapa pun dapat berubah, akses langsung tanpa objek, dll.)
Untuk info lebih lanjut baca ini Terima kasih.
sumber
Mungkin disarankan bahwa dalam kebanyakan kasus di mana Anda menggunakan variabel statis, Anda benar-benar ingin menggunakan pola tunggal .
Masalah dengan negara-negara global adalah bahwa kadang-kadang apa yang masuk akal sebagai global dalam konteks yang lebih sederhana, perlu sedikit lebih fleksibel dalam konteks praktis, dan di sinilah pola tunggal menjadi berguna.
sumber
Namun alasan lain: kerapuhan.
Jika Anda memiliki kelas, kebanyakan orang berharap dapat membuatnya dan menggunakannya sesuka hati.
Anda dapat mendokumentasikannya bukan kasusnya, atau melindunginya (pola tunggal / pabrik) - tapi itu pekerjaan tambahan, dan karenanya merupakan biaya tambahan. Bahkan kemudian, di sebuah perusahaan besar, kemungkinan seseorang akan mencoba di beberapa titik untuk menggunakan kelas Anda tanpa sepenuhnya memperhatikan semua komentar atau pabrik yang bagus.
Jika Anda banyak menggunakan variabel statis, itu akan rusak. Bug itu mahal.
Antara peningkatan kinerja .0001% dan ketahanan untuk berubah oleh pengembang yang berpotensi tidak mengerti, dalam banyak kasus ketahanan adalah pilihan yang baik.
sumber
Saya menemukan variabel statis lebih nyaman digunakan. Dan saya menganggap bahwa mereka juga efisien (Harap perbaiki saya jika saya salah) karena jika saya harus membuat 10.000 panggilan ke suatu fungsi dalam suatu kelas, saya akan senang untuk membuat metode ini statis dan menggunakan class.methodCall () yang mudah di atasnya bukannya mengacaukan memori dengan 10.000 contoh kelas, Benar?
Saya mengerti apa yang Anda pikirkan, tetapi pola Singleton sederhana akan melakukan hal yang sama tanpa harus membuat instance 10.000 objek.
metode statis dapat digunakan, tetapi hanya untuk fungsi yang berhubungan dengan domain objek dan tidak perlu atau menggunakan properti internal objek.
ex:
sumber
Class.Instance
) hampir tidak lebih baik daripada variabel statis. Ini sedikit lebih dapat diuji, tetapi masih jauh lebih buruk daripada desain di mana Anda kebetulan membuat satu contoh bukannya membangun kode Anda dengan asumsi hanya ada satu.Class.Instance
) yang membawa keadaan bisa berubah adalah IMO desain yang buruk. Dalam hal ini saya sangat suka desain di mana saya mendapatkan lajang saya perlu menggunakan diteruskan sebagai parameter ke dalam kelas yang menggunakannya (biasanya dengan bantuan DI). Lajang klasik yang tidak dapat diubah secara logis adalah IMO yang baik.Masalah 'Statika menjadi jahat' lebih merupakan masalah tentang negara global. Waktu yang tepat untuk variabel menjadi statis, adalah jika tidak pernah memiliki lebih dari satu negara; Alat IE yang harus dapat diakses oleh seluruh kerangka kerja dan selalu mengembalikan hasil yang sama untuk panggilan metode yang sama tidak pernah 'jahat' seperti statika. Seperti untuk komentar Anda:
Statika adalah pilihan ideal dan efisien untuk variabel / kelas yang tidak pernah berubah .
Masalah dengan negara global adalah ketidakkonsistenan inheren yang dapat diciptakannya. Dokumentasi tentang pengujian unit sering mengatasi masalah ini, karena setiap saat ada keadaan global yang dapat diakses oleh lebih dari beberapa objek yang tidak terkait, pengujian unit Anda akan tidak lengkap, dan tidak berbutir 'unit'. Seperti yang disebutkan dalam artikel ini tentang negara global dan lajang , jika objek A dan B tidak terkait (karena dalam satu tidak secara tegas diberikan referensi ke yang lain), maka A seharusnya tidak dapat mempengaruhi keadaan B.
Ada beberapa pengecualian untuk larangan negara global dalam kode yang baik, seperti jam. Waktu bersifat global, dan - dalam arti tertentu - waktu mengubah keadaan objek tanpa memiliki hubungan kode.
sumber
$ 0,02 saya adalah bahwa beberapa jawaban ini membingungkan masalah ini, daripada mengatakan "statika itu buruk" Saya pikir lebih baik untuk berbicara tentang pelingkupan dan contoh.
Apa yang akan saya katakan adalah bahwa statis adalah variabel "kelas" - itu mewakili nilai yang dibagikan di semua contoh kelas itu. Biasanya harus dicakup juga (dilindungi atau pribadi untuk kelas dan instansnya).
Jika Anda berencana untuk menempatkan perilaku tingkat kelas di sekitarnya dan memaparkannya ke kode lain, maka singleton mungkin merupakan solusi yang lebih baik untuk mendukung perubahan di masa depan (seperti yang disarankan @Jessica). Ini karena Anda dapat menggunakan antarmuka pada tingkat instance / singleton dengan cara yang tidak dapat Anda gunakan di tingkat kelas - khususnya warisan.
Beberapa pemikiran tentang mengapa saya pikir beberapa aspek dalam jawaban lain bukanlah inti dari pertanyaan ...
Statika bukan "global". Dalam Java scoping dikontrol secara terpisah dari static / instance.
Concurrency tidak kalah berbahaya untuk statika daripada metode instance. Itu masih menyatakan bahwa perlu dilindungi. Tentu Anda memiliki 1000 instance dengan masing-masing variabel instan dan hanya satu variabel statis, tetapi jika kode yang mengakses keduanya tidak ditulis dengan cara aman, Anda masih kacau - mungkin perlu sedikit waktu lebih lama bagi Anda untuk menyadarinya .
Mengelola siklus hidup adalah argumen yang menarik, tetapi saya pikir itu kurang penting. Saya tidak melihat mengapa lebih sulit untuk mengelola sepasang metode kelas seperti init () / clear () daripada penciptaan dan penghancuran instance tunggal. Bahkan, beberapa orang mungkin mengatakan singleton sedikit lebih rumit karena GC.
PS, Dalam hal Smalltalk, banyak dialeknya memang memiliki variabel kelas, tetapi dalam kelas Smalltalk sebenarnya adalah instance dari Metaclass sehingga mereka benar-benar adalah variabel pada instance Metaclass. Meski begitu, saya akan menerapkan aturan praktis yang sama. Jika mereka digunakan untuk keadaan bersama di seluruh instance maka ok. Jika mereka mendukung fungsi publik, Anda harus melihat Singleton. Sigh, aku sungguh merindukan Smalltalk ....
sumber
Ada dua pertanyaan utama dalam posting Anda.
Pertama, tentang variabel statis. Variabel statis sama sekali tidak perlu dan penggunaannya dapat dihindari dengan mudah. Dalam bahasa OOP secara umum, dan di Java khususnya, parameter fungsi disusun berdasarkan referensi, ini artinya, jika Anda meneruskan objek ke funciont, Anda meneruskan pointer ke objek, jadi Anda tidak perlu mendefinisikan variabel statis karena Anda bisa meneruskan pointer ke objek ke lingkup apa pun yang membutuhkan informasi ini. Bahkan jika ini menyiratkan bahwa Anda akan mengisi memori Anda dengan pointer, ini tidak akan mewakili kinerja yang buruk karena sistem pagging memori aktual dioptimalkan untuk menangani hal ini, dan mereka akan mempertahankan dalam memori halaman yang dirujuk oleh pointer yang Anda berikan ke pointer baru. cakupan; penggunaan variabel statis dapat menyebabkan sistem memuat halaman memori di mana mereka disimpan ketika mereka perlu diakses (ini akan terjadi jika halaman tersebut belum diakses dalam waktu yang lama). Praktik yang baik adalah menyatukan semua stuf statis itu dalam beberapa "konfigurasi clases" kecil, ini akan memastikan sistem menempatkan semuanya di halaman memori yang sama.
Kedua, tentang metode statis. Metode statis tidak terlalu buruk, tetapi mereka dapat dengan cepat mengurangi kinerja. Sebagai contoh, pikirkan tentang metode yang membandingkan dua objek kelas dan mengembalikan nilai yang menunjukkan objek mana yang lebih besar (metode perbandingan tipikal) metode ini bisa statis atau tidak, tetapi ketika menjalankannya bentuk non statis akan lebih efisien karena harus menyelesaikan hanya dua referensi (satu untuk setiap objek) hadapi tiga referensi yang harus menyelesaikan versi statis dari metode yang sama (satu untuk kelas ditambah dua, satu untuk setiap objek). Tetapi seperti yang saya katakan, ini tidak terlalu buruk, jika kita melihat pada kelas Matematika, kita dapat menemukan banyak fungsi matematika yang didefinisikan sebagai metode statis. Ini benar-benar lebih efisien daripada menempatkan semua metode ini di kelas mendefinisikan angka,
Dalam kesimpulan: Hindari penggunaan variabel statis dan temukan keseimbangan kinerja yang benar ketika berhadapan dengan metode statis atau non-statis.
PS: Maaf untuk bahasa Inggris saya.
sumber
Tidak ada yang salah dengan variabel statis per se. Hanya sintaksis Java yang rusak. Setiap kelas Java sebenarnya mendefinisikan dua struktur - objek tunggal yang merangkum variabel statis, dan sebuah instance. Mendefinisikan keduanya di blok sumber yang sama adalah kejahatan murni, dan menghasilkan kode yang sulit dibaca. Scala melakukan itu dengan benar.
sumber
a) Alasan tentang program.
Jika Anda memiliki program kecil hingga menengah, di mana variabel statis Global.foo diakses, panggilan ke sana biasanya datang entah dari mana - tidak ada jalur, dan oleh karena itu tidak ada garis waktu, bagaimana variabel datang ke tempat itu, di mana ia digunakan. Sekarang, bagaimana saya tahu siapa yang mengaturnya ke nilai sebenarnya? Bagaimana saya tahu, apa yang terjadi, jika saya memodifikasinya sekarang? Saya telah memahami seluruh sumber, untuk mengumpulkan semua akses, untuk mengetahui, apa yang sedang terjadi.
Jika Anda tahu cara menggunakannya, karena Anda baru saja menulis kode, masalahnya tidak terlihat, tetapi jika Anda mencoba memahami kode asing, Anda akan mengerti.
b) Apakah Anda benar-benar hanya membutuhkannya?
Variabel statis sering mencegah beberapa program dari jenis yang sama berjalan di JVM yang sama dengan nilai yang berbeda. Anda sering tidak melihat penggunaan, di mana lebih dari satu contoh program Anda berguna, tetapi jika itu berkembang, atau jika berguna bagi orang lain, mereka mungkin mengalami situasi, di mana mereka ingin memulai lebih dari satu contoh program Anda .
Hanya lebih atau kurang kode tidak berguna yang tidak akan digunakan oleh banyak orang dalam waktu yang lebih lama dengan cara intensif mungkin cocok dengan variabel statis.
sumber
semuanya (dapat :) memiliki tujuannya, jika Anda memiliki banyak utas yang perlu berbagi / cache data dan juga semua memori yang dapat diakses (jadi Anda tidak membagi ke dalam konteks dalam satu JVM) statis adalah pilihan terbaik
-> tentu saja Anda dapat memaksa hanya satu contoh, tetapi mengapa?
saya menemukan beberapa komentar di utas ini jahat, bukan statika;)
sumber
Variabel statis tidak baik atau jahat. Mereka mewakili atribut yang menggambarkan seluruh kelas dan bukan contoh tertentu. Jika Anda perlu memiliki penghitung untuk semua instance dari kelas tertentu, variabel statis akan menjadi tempat yang tepat untuk menyimpan nilai.
Masalah muncul ketika Anda mencoba menggunakan variabel statis untuk memegang nilai terkait contoh.
sumber
Semua jawaban di atas menunjukkan mengapa statika itu buruk. Alasan mereka jahat adalah karena memberikan kesan yang salah bahwa Anda menulis kode berorientasi objek, padahal sebenarnya Anda tidak. Itu benar-benar kejahatan.
sumber
Ada banyak jawaban bagus di sini, menambahkannya,
Memori: Variabel statis hidup selama loader kelas hidup [secara umum sampai VM mati], tetapi ini hanya dalam kasus objek massal / referensi yang disimpan sebagai statis.
Modularisasi: pertimbangkan konsep-konsep seperti IOC, dependencyInjection, proxy, dll. Semua sepenuhnya bertentangan dengan implementasi kopling / statis.
Lainnya Con: Keselamatan Thread, Testability
sumber
Pikirkan bahwa jika Anda memiliki aplikasi dengan banyak pengguna dan Anda telah menentukan bentuk statis, maka setiap pengguna juga akan memodifikasi semua bentuk lain dari pengguna lain.
sumber
Saya pikir penggunaan variabel global yang berlebihan dengan kata kunci statis juga akan menyebabkan kebocoran memori pada beberapa titik misalnya di aplikasi
sumber
Dari sudut pandang saya,
static
seharusnya hanya variabel yang hanya dibaca data atau variabel yang dibuat oleh konvensi .Sebagai contoh, kami memiliki beberapa proyek, dan kami memiliki daftar negara, bahasa, peran pengguna, dll. Dan kami memiliki kelas untuk mengatur data ini. kami benar-benar yakin bahwa aplikasi tidak akan berfungsi tanpa daftar ini. jadi yang pertama yang kita lakukan pada aplikasi init adalah memeriksa daftar ini untuk pembaruan dan mendapatkan daftar ini dari api (jika perlu). Jadi kami setuju bahwa data ini "selalu" ada di aplikasi. Secara praktis hanya membaca data sehingga kita tidak perlu mengurus keadaannya - memikirkan kasus ini kita benar-benar tidak ingin memiliki banyak contoh data tersebut - kasus ini terlihat sebagai kandidat yang sempurna untuk menjadi statis .
sumber
Saya sering bermain dengan statika dan mungkin saya memberi Anda jawaban yang sedikit berbeda - atau mungkin cara yang sedikit berbeda untuk melihatnya?
Ketika saya menggunakan statika dalam suatu kelas (Anggota dan metode keduanya), saya akhirnya mulai memperhatikan bahwa kelas saya sebenarnya adalah dua kelas yang berbagi tanggung jawab - ada bagian "Statis" yang bertindak sangat mirip dengan seorang lajang dan ada yang tidak. -bagian statis (kelas normal). Sejauh yang saya tahu Anda selalu dapat memisahkan dua kelas sepenuhnya dengan hanya memilih semua statika untuk satu kelas dan non-statika untuk yang lain.
Ini sering terjadi ketika saya memiliki koleksi statis di dalam kelas yang menyimpan instance kelas dan beberapa metode statis untuk mengelola koleksi. Setelah Anda memikirkannya, jelas bahwa kelas Anda tidak melakukan "Hanya satu hal", itu menjadi koleksi dan melakukan sesuatu yang sama sekali berbeda.
Sekarang, mari kita sedikit memperbaiki masalahnya: Jika Anda membagi kelas Anda menjadi satu kelas di mana semuanya statis dan yang lainnya hanya merupakan "Kelas Normal" dan lupakan "Kelas Normal" maka pertanyaan Anda menjadi murni kelas statis vs Singleton yang dibahas panjang lebar di sini (dan mungkin selusin pertanyaan lain).
sumber