Mengapa tidak ada fitur Konstan di Jawa?

140

Saya mencoba mengidentifikasi alasan di balik konstanta di Jawa. Saya telah belajar bahwa Java memungkinkan kita untuk mendeklarasikan konstanta dengan menggunakan finalkata kunci.

Pertanyaan saya adalah mengapa Java tidak memperkenalkan fitur Constant ( const). Karena banyak orang mengatakan itu berasal dari C ++, di C ++ kami memiliki constkata kunci.

Silakan bagikan pemikiran Anda.

gmhk
sumber
2
Ada adalah sebuah constkata kunci, tetapi tidak ada fitur yang mendasarinya. Koreksi judul dan tag Anda sesuai.
Marquis of Lorne

Jawaban:

142

Setiap kali saya beralih dari pengkodean C ++ yang berat ke Java, saya butuh sedikit waktu untuk beradaptasi dengan kurangnya const-correctness di Java. Penggunaan constdalam C ++ ini jauh berbeda dari sekadar mendeklarasikan variabel konstan, jika Anda tidak tahu. Pada dasarnya, ini memastikan bahwa suatu objek tidak berubah ketika diakses melalui jenis khusus dari pointer yang disebut const-pointer Ketika di Jawa, di tempat-tempat di mana saya biasanya ingin mengembalikan sebuah pointer-pointer, saya malah mengembalikan referensi dengan tipe antarmuka hanya mengandung metode yang seharusnya tidak memiliki efek samping. Sayangnya, ini tidak dipaksakan oleh langauge.

Wikipedia menawarkan informasi berikut tentang subjek:

Menariknya, spesifikasi bahasa Java menganggap const sebagai kata kunci yang dicadangkan - yaitu, yang tidak dapat digunakan sebagai pengenal variabel - tetapi tidak menetapkan semantik untuk itu. Diperkirakan bahwa reservasi kata kunci terjadi untuk memungkinkan perpanjangan bahasa Java untuk memasukkan metode const C ++ dan pointer ke tipe const. Tiket permintaan peningkatan dalam Java Community Process untuk menerapkan kebenaran const di Jawa ditutup pada tahun 2005, menyiratkan bahwa kebenaran const mungkin tidak akan pernah menemukan jalannya ke dalam spesifikasi resmi Java.

Gunslinger47
sumber
10
Jawa finalserupa.
reinierpost
62
Bukan itu. finalMetode misalnya bekerja sangat berbeda dari constmetode C ++ .
dom0
7
@reinierpost Kata finalkunci pada properti atau variabel hanya memastikan bahwa properti atau variabel hanya ditugaskan satu kali . Seseorang masih dapat mengubah keadaan objek ini dengan, misalnya, memanggil beberapa metode dengan efek samping. finalagak mirip untuk menumpuk alokasi C ++ dalam hal merujuk ke objek daripada pointer, tapi hanya itu. Ini tentu saja di samping apa yang sudah dikatakan dom0.
Tim
9
finaldi Jawa tampaknya bekerja seperti C ++ constuntuk tipe nilai, tetapi lebih seperti C ++ non-const T&untuk tipe referensi
Mark K Cowan
1
akhir adalah kata kunci skizofrenia. Meskipun mencegah penugasan kembali, itu juga digunakan untuk mengekspos variabel untuk penutupan. Saya mungkin ingin mencegah penugasan kembali tetapi tidak mengekspos variabel-variabel itu, tetapi tidak ada cara untuk melakukannya. Menurut saya, ini fitur bahasa yang agak kurang dipikirkan.
David Bradley
82

Apa constartinya
Pertama, sadari bahwa semantik kata kunci "const" memiliki arti berbeda bagi orang yang berbeda:

  • referensi baca-saja - Java finalsemantik - variabel referensi itu sendiri tidak dapat dipindahkan untuk menunjuk ke instance lain (lokasi memori), tetapi instance itu sendiri dapat dimodifikasi
  • referensi yang hanya dapat dibaca - C constpointer / semantik referensi - berarti referensi ini tidak dapat digunakan untuk memodifikasi instance (mis. tidak dapat menetapkan variabel instan, tidak dapat memanggil metode yang dapat ditransmisikan) - hanya memengaruhi variabel referensi, sehingga referensi non-const menunjuk ke instance yang sama dapat memodifikasi instance
  • objek immutable - berarti instance itu sendiri tidak dapat dimodifikasi - berlaku untuk instance, sehingga referensi non-const tidak akan diizinkan atau tidak dapat digunakan untuk memodifikasi instance
  • beberapa kombinasi di atas ?
  • orang lain ?

Mengapa atau Mengapa Tidakconst
Kedua, jika Anda benar-benar ingin menggali beberapa argumen "pro" vs "con", lihat diskusi di bawah permintaan untuk peningkatan ini (bug) "bug". RFE ini meminta fitur "const-readable only" -type "const" fitur. Dibuka pada tahun 1999 dan kemudian ditutup / ditolak oleh Sun pada tahun 2005, topik "const" sangat diperdebatkan:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4211070

Meskipun ada banyak argumen bagus di kedua sisi, beberapa alasan yang sering dikutip (tetapi tidak selalu meyakinkan atau jelas) constmeliputi:

  • mungkin memiliki membingungkan semantik yang dapat disalahgunakan dan / atau disalahgunakan (lihat Apa constberarti di atas)
  • dapat menduplikasi kemampuan yang tersedia (misalnya merancang kelas yang tidak dapat diubah, menggunakan antarmuka yang tidak dapat diubah)
  • mungkin fitur creep, yang mengarah ke kebutuhan untuk perubahan semantik lainnya seperti dukungan untuk melewatkan objek berdasarkan nilai

Sebelum ada yang mencoba memperdebatkan saya tentang apakah ini alasan baik atau buruk, perhatikan bahwa ini bukan alasan saya . Mereka hanyalah "inti" dari beberapa alasan yang saya dapatkan dari membaca diskusi RFE. Saya sendiri belum tentu setuju dengan mereka - Saya hanya mencoba mengutip mengapa beberapa orang (bukan saya) merasa constkata kunci mungkin bukan ide yang baik. Secara pribadi, saya ingin semantik "const" yang lebih banyak untuk diperkenalkan ke bahasa dengan cara yang jelas.

Bert F
sumber
2
Memberi +1 hanya untuk bagian kedua dari jawaban Anda. Banyak banyak kata kunci yang memiliki semantik non-sepele. Apakah volatilesangat sederhana untuk dipahami? Atau final? Ah.
einpoklum
OTOH, Java dirancang untuk menggunakan sesedikit mungkin fitur-fitur non-sepele itu. Dan saya tidak mengatakan bahwa mereka mencapai tujuan itu (atau bahwa Jawa belum menjauh dari tujuan itu). Tetapi mengecualikannya karena alasan itu mungkin masih memiliki manfaat. Bahwa ada hal-hal rumit lainnya adalah semakin banyak alasan untuk tidak memperkenalkan lebih banyak (atau Anda akan berakhir dengan bahasa D).
Maarten Bodewes
7

const dalam C ++ tidak berarti bahwa suatu nilai adalah konstanta.

const dalam C ++ menyiratkan bahwa klien kontrak berjanji untuk tidak mengubah nilainya.

Apakah nilai constekspresi berubah menjadi lebih jelas jika Anda berada di lingkungan yang mendukung konkurensi berbasis utas.

Karena Java dirancang sejak awal untuk mendukung konkurensi thread dan lock, Java tidak menambah kebingungan dengan membebani istilah untuk memiliki semantik yang finaldimiliki.

misalnya:

#include <iostream>

int main ()
{
    volatile const int x = 42;

    std::cout << x << std::endl;

    *const_cast<int*>(&x) = 7;

    std::cout << x << std::endl;

    return 0;
}

output 42 maka 7.

Meskipun xditandai sebagai const, sebagai alias non-const dibuat, xbukan konstanta. Tidak setiap kompiler memerlukan volatileperilaku ini (meskipun setiap kompiler diizinkan untuk menyejajarkan konstanta)

Dengan sistem yang lebih rumit, Anda mendapatkan alias const / non-const tanpa menggunakan const_cast, jadi biasakan berpikir bahwa const berarti sesuatu yang tidak akan berubah menjadi semakin berbahaya. consthanya berarti bahwa kode Anda tidak dapat mengubahnya tanpa gips, bukan karena nilainya konstan.

Pete Kirkham
sumber
3
const int x = 42; - x adalah konstanta
2
@ Neil Jika Anda memiliki satu objek atau variabel alias oleh pointer const dan non-const, maka nilai alias const dapat diubah oleh alias non-const. Karena constitu bukan berarti nilai konstan. Ini berarti bahwa klien dari suatu nilai dibatasi untuk tidak mengubahnya. Dalam contoh Anda tidak ada alias, sehingga semua pengguna berada di bawah kendala yang sama. Ini tidak terjadi secara umum. constefek klien, bukan nilai - katanya Anda tidak bisa mengubahnya, bukan bahwa itu tidak akan berubah.
Pete Kirkham
1
Benar-benar adalah tentang apa yang harus dilakukan programmer , bukan apa yang bisa mereka lakukan . Saya pikir Anda semua sepertinya sudah mengerti. Hanya ingin menambahkan beberapa sen yang dapat menarik bagi pembaca sebab-akibat: Desain pola seperti immutable interfacedan immutable objectmerupakan cara lain (dapat dikalahkan dengan pemain dan refleksi) untuk meniru const di Jawa. Const "True" dapat dilakukan dengan SealedObject , sayangnya itu menghancurkan use case dari objek kita.
Martin Andersson
6
Orang harus mencatat bahwa hasil dari program Anda tidak ditentukan. const_cast tidak ada untuk mengubah variabel const, itu ada untuk meneruskan variabel const ke API yang tidak benar const, tetapi juga tidak mengubah nilai. Saya pikir kebiasaan berpikir bahwa sesuatu const tidak akan berubah adalah sesuatu yang baik karena jika mereka berubah, itu berarti program Anda mengandung peretasan yang mungkin pecah kapan saja tergantung pada kompiler yang digunakan.
Cygon
1
Mengubah nilai lahir ke konstan adalah perilaku yang tidak terdefinisi. Disk Anda mungkin sudah diformat.
Zhe Yang
5

Ini sedikit pertanyaan lama, tapi saya pikir saya tetap akan menyumbangkan 2 sen saya karena utas ini muncul dalam percakapan hari ini.

Ini tidak persis menjawab mengapa tidak ada const? tetapi bagaimana membuat kelas Anda tidak berubah. (Sayangnya saya belum memiliki reputasi yang cukup untuk memposting sebagai komentar atas jawaban yang diterima)

Cara untuk menjamin kekekalan pada suatu objek adalah dengan merancang kelas Anda lebih hati-hati agar tidak berubah. Ini membutuhkan sedikit perawatan lebih dari kelas yang bisa berubah.

Ini kembali ke Item 15 Java Efektif Josh Bloch - Minimalkan Mutabilitas . Jika Anda belum membaca buku itu, ambil salinannya dan bacalah beberapa kali. Saya jamin itu akan meningkatkan "permainan java" kiasan Anda .

Dalam item 15, Bloch menyarankan agar Anda membatasi mutabilitas kelas untuk memastikan status objek.

Mengutip buku secara langsung:

Kelas yang tidak berubah hanyalah kelas yang instansnya tidak dapat dimodifikasi. Semua informasi yang terkandung dalam setiap instance disediakan ketika dibuat dan diperbaiki untuk seumur hidup objek. Pustaka platform Java berisi banyak kelas yang tidak dapat diubah, termasuk String, kelas primitif kotak, dan BigInteger dan BigDecimal. Ada banyak alasan bagus untuk ini: Kelas yang tidak dapat berubah lebih mudah untuk dirancang, diimplementasikan, dan digunakan daripada kelas yang bisa berubah. Mereka kurang rentan terhadap kesalahan dan lebih aman.

Bloch kemudian menjelaskan cara membuat kelas Anda tidak berubah, dengan mengikuti 5 aturan sederhana:

  1. Jangan berikan metode apa pun yang mengubah status objek (mis., Setter, alias mutator )
  2. Pastikan bahwa kelas tidak dapat diperpanjang (ini berarti menyatakan kelas itu sendiri sebagai final).
  3. Buat semua bidang final.
  4. Buat semua bidang private.
  5. Pastikan akses eksklusif ke komponen yang dapat berubah. (dengan membuat salinan defensif dari objek)

Untuk lebih jelasnya saya sangat merekomendasikan mengambil salinan buku.

grego
sumber
3
const di C ++ JAUH lebih fleksibel daripada immutabilitas skala penuh. Dalam arti tertentu, 'const' dapat dilihat sebagai 'tidak berubah dalam konteks khusus ini'. Contoh: Saya memiliki kelas yang tidak dapat diubah, TETAPI saya ingin memastikan bahwa itu tidak dimodifikasi melalui API publik tertentu. Membuat antarmuka (dan mengembalikannya untuk API publik) seperti yang disarankan oleh Gunslinger47 mencapai hal yang sama di Jawa, tetapi anak laki-laki - itu IS jelek (dan sebagainya - itu diabaikan oleh sebagian besar pengembang Java, yang menyebabkan kekacauan signifikan yang tidak perlu) .. .
No-Bugs Kelinci
3

Semantik C ++ constsangat berbeda dengan Java final. Jika perancang telah menggunakannya, constitu tidak perlu membingungkan.

Fakta bahwa itu constadalah kata yang dicadangkan menunjukkan bahwa para perancang punya ide untuk diimplementasikan const, tetapi sejak itu mereka memutuskan untuk tidak melakukannya; lihat bug tertutup ini . Alasan lain termasuk menambahkan dukungan untuk gaya C ++ constakan menyebabkan masalah kompatibilitas.

Stephen C
sumber
-1

Ada cara untuk membuat variabel "const" di Java, tetapi hanya untuk kelas-kelas tertentu. Cukup tentukan kelas dengan properti final dan subkelasnya. Kemudian gunakan kelas dasar di mana Anda ingin menggunakan "const". Demikian juga, jika Anda perlu menggunakan metode "const", tambahkan mereka ke kelas dasar. Kompiler tidak akan memungkinkan Anda untuk memodifikasi apa yang dianggapnya sebagai metode final kelas dasar, tetapi ia akan membaca dan memanggil metode pada subkelas.

pengguna1122069
sumber
Bisakah Anda memberikan beberapa contohnya?
NO_NAME
class MYString mengimplementasikan GetString {private final String aaaa; public String getString (); } class MutableString mengimplementasikan GetString {private String aaaa2; public String getString (); public String setString ()}
user1122069
-2

Akan ada dua cara untuk mendefinisikan konstanta - constdan static final, dengan semantik yang sama persis. Selanjutnya static finalmenggambarkan perilaku lebih baik daripadaconst

Bozho
sumber
@Bozho, Anda mengatakan perilaku yang lebih baik daripada Const, seperti apa itu? dapatkah Anda membagikan contoh
gmhk
baik, variabelnya static(bukan milik instance tertentu) dan final- tidak dapat diubah.
Bozho
-2

Anda dapat menggunakan final statis untuk membuat sesuatu yang berfungsi mirip dengan Const, saya telah menggunakan ini di masa lalu.

protected static final int cOTHER = 0;
protected static final int cRPM = 1;
protected static final int cSPEED = 2;
protected static final int cTPS = 3;
protected int DataItemEnum = 0;

public static final int INVALID_PIN = -1;
public static final int LED_PIN = 0;
hamish
sumber
Turun karena optimisasi berbasis rumor karena saya mendengar desas-desus bahwa ini adalah strategi yang tidak efektif.
afarley
Saya menghapus rumor dari jawabannya. Anda masih dapat menggunakan int final statis untuk membuat kode gaya const.
hamish
Oke, saya telah menghapus downvote saya. Mungkin beberapa downvotes lainnya adalah tentang pernyataan switch (apa hubungannya dengan sisa contoh Anda?)
afarley
dalam pernyataan switch saya menggunakan cRPM seolah-olah itu adalah const. cukup benar, mengingat hal di atas. jadi ya saya telah menghapus sakelar.
hamish