เหตุใดจึงไม่มีคุณสมบัติคงที่ใน Java


140

ฉันพยายามระบุเหตุผลของค่าคงที่ใน Java ฉันได้เรียนรู้ว่า Java ช่วยให้เราประกาศค่าคงที่โดยใช้finalคำหลัก

คำถามของฉันคือทำไม Java ไม่แนะนำคุณลักษณะคงที่ ( const) เนื่องจากหลายคนบอกว่ามาจาก C ++ ใน C ++ เรามีconstคำหลัก

กรุณาแบ่งปันความคิดของคุณ


2
มีเป็นconstคำหลัก แต่ไม่มีคุณลักษณะพื้นฐาน แก้ไขชื่อและแท็กให้ถูกต้อง
มาร์ควิสแห่ง Lorne

คำตอบ:


142

ทุกครั้งที่ฉันเปลี่ยนจากการเข้ารหัส C ++ ไปเป็นจาวาจะต้องใช้เวลาสักครู่ในการปรับตัวให้เข้ากับการขาดความถูกต้องของภาษาใน Java การใช้งานconstใน C ++ นี้แตกต่างจากการประกาศตัวแปรคงที่ถ้าคุณไม่รู้ โดยพื้นฐานแล้วมันช่วยให้มั่นใจว่าวัตถุนั้นไม่สามารถเปลี่ยนแปลงได้เมื่อเข้าถึงผ่านตัวชี้ชนิดพิเศษที่เรียกว่า const-pointer เมื่ออยู่ใน Java ในสถานที่ที่ปกติฉันต้องการคืนค่า const-pointer ฉันกลับไปอ้างอิงด้วยชนิดอินเตอร์เฟส มีวิธีการเท่านั้นที่ไม่ควรมีผลข้างเคียง น่าเสียดายที่สิ่งนี้ไม่ได้ถูกบังคับใช้โดยอีเมล์

Wikipedia เสนอข้อมูลต่อไปนี้ในหัวข้อ:

ที่น่าสนใจคือข้อกำหนดภาษาจาวาถือว่า const เป็นคำหลักที่สงวนไว้ - คือสิ่งที่ไม่สามารถใช้เป็นตัวระบุตัวแปร - แต่ไม่ได้กำหนดซีแมนทิกส์ให้กับมัน มันคิดว่าการจองคำหลักเกิดขึ้นเพื่อให้ส่วนขยายของภาษาจาวารวม C + + - วิธี const สไตล์และชี้ไปที่ประเภท const ตั๋วร้องขอการปรับปรุงในกระบวนการ Java Community สำหรับการใช้ความถูกต้อง const ใน Java ถูกปิดในปี 2005 ซึ่งหมายความว่าการแก้ไขความถูกต้องของ const อาจจะไม่พบทางที่จะนำไปสู่ข้อกำหนดของ Java อย่างเป็นทางการ


10
Java finalนั้นคล้ายกัน
reinierpost

62
ไม่มันไม่ใช่ finalวิธีการทำงานตัวอย่างแตกต่างจากconstวิธีC ++ อย่างสิ้นเชิง
dom0

7
@reinierpost finalคำหลักที่เกี่ยวกับคุณสมบัติหรือตัวแปรเพียงเพื่อให้แน่ใจว่าทรัพย์สินหรือตัวแปรที่ได้รับมอบหมายเท่านั้นที่จะครั้งเดียว เรายังคงสามารถเปลี่ยนสถานะของวัตถุนี้โดยการเรียกวิธีการที่มีผลข้างเคียง finalค่อนข้างคล้ายกันในการจัดสรรสแต็คของ C ++ ในแง่ของการอ้างถึงวัตถุมากกว่าตัวชี้ แต่นั่นคือทั้งหมดที่มันเป็น นี่คือหลักสูตรนอกเหนือจากที่ dom0 พูดไปแล้ว
ทิม

9
finalใน Java ดูเหมือนว่าจะทำงานเหมือน C ++ constสำหรับประเภทของค่า แต่ก็เหมือน C ++ ที่ไม่ใช่แบบ const T&สำหรับประเภทการอ้างอิง
Mark K Cowan

1
สุดท้ายคือคำหลักที่เป็นโรคจิตเภท แม้ว่าจะป้องกันการกำหนดใหม่ แต่ก็ยังใช้เพื่อเปิดเผยตัวแปรในการปิด ฉันอาจต้องการป้องกันการกำหนดใหม่ แต่ไม่เปิดเผยตัวแปรเหล่านั้น แต่ไม่มีวิธีที่จะทำ ในความคิดของฉันมันเป็นคุณสมบัติทางภาษาที่ค่อนข้างต่ำ
David Bradley

82

อะไรconstหมายถึง
ครั้งแรกที่ตระหนักดีว่าความหมายของ "const" หมายถึงคำหลักสิ่งที่แตกต่างกับคนที่แตกต่างกัน:

  • การอ้างอิงแบบอ่านอย่างเดียว - ซีแมนทิกส์ Java final- ตัวแปรอ้างอิงไม่สามารถกำหนดใหม่ให้ชี้ไปยังอินสแตนซ์อื่น (ตำแหน่งหน่วยความจำ) แต่อินสแตนซ์นั้นสามารถแก้ไขได้
  • การอ้างอิงแบบอ่านได้อย่างเดียว - ซีพอยต์const/ ซีแมนทิกส์อ้างอิง - หมายถึงการอ้างอิงนี้ไม่สามารถใช้ในการปรับเปลี่ยนอินสแตนซ์ (เช่นไม่สามารถกำหนดให้กับตัวแปรอินสแตนซ์ไม่สามารถเรียกใช้วิธีที่ไม่แน่นอนได้) อินสแตนซ์เดียวกันสามารถแก้ไขอินสแตนซ์ได้
  • วัตถุที่ไม่เปลี่ยนรูป - หมายความว่าไม่สามารถปรับเปลี่ยนอินสแตนซ์ของตัวเองได้ - ใช้กับอินสแตนซ์ดังนั้นการอ้างอิงที่ไม่ใช่ const ใด ๆ จะไม่ได้รับอนุญาตหรือไม่สามารถใช้เพื่อแก้ไขอินสแตนซ์ได้
  • การรวมกันของข้างต้นบางส่วน ?
  • คนอื่น ๆ ?

ทำไมหรือเพราะเหตุใดไม่ใช่const
วินาทีถ้าคุณต้องการขุดลงในอาร์กิวเมนต์ "pro" vs "con" ให้ดูการอภิปรายภายใต้คำขอ "เพิ่ม" (RFE) RFE นี้ร้องขอคุณลักษณะ "การอ้างอิงแบบอ่านอย่างเดียว" -type "const" เปิดในปี 1999 และจากนั้นปิด / ปฏิเสธโดย Sun ในปี 2005 หัวข้อ "const" ถูกถกเถียงกันอย่างจริงจัง:

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

ในขณะที่มีข้อโต้แย้งที่ดีมากมายทั้งสองด้านเหตุผลบางประการที่อ้างถึง (แต่ไม่จำเป็นต้องมีเหตุผลที่น่าสนใจหรือชัดเจน) กับconst:

  • อาจจะมีความหมายทำให้เกิดความสับสนที่อาจถูกนำไปใช้และ / หรือถูกทารุณกรรม (ดูอะไรconstหมายถึงด้านบน)
  • อาจทำซ้ำความสามารถที่มีอยู่เป็นอย่างอื่น (เช่นการออกแบบคลาสที่ไม่เปลี่ยนรูปโดยใช้ส่วนต่อประสานที่ไม่เปลี่ยนรูป)
  • อาจเป็นลักษณะการคืบนำไปสู่ความต้องการการเปลี่ยนแปลงทางความหมายอื่น ๆ เช่นการสนับสนุนสำหรับการส่งวัตถุตามค่า

ก่อนที่ทุกคนพยายามที่จะมีการอภิปรายเกี่ยวกับว่าผมเหล่านี้จะดีหรือไม่ดีเหตุผลทราบว่าเหล่านี้จะไม่ได้เป็นเหตุผลของผม พวกเขาเป็นเพียง "ส่วนสำคัญ" ของเหตุผลบางอย่างที่ฉันรวบรวมจากการข้ามการอภิปราย RFE ฉันไม่เห็นด้วยกับพวกเขาด้วยตัวเอง - ฉันแค่พยายามอ้างว่าทำไมบางคน (ไม่ใช่ฉัน) อาจรู้สึกว่าconstคำหลักอาจไม่ใช่ความคิดที่ดี โดยส่วนตัวแล้วฉันชอบความหมาย "const" มากกว่าที่จะแนะนำให้รู้จักกับภาษาในลักษณะที่ไม่คลุมเครือ


2
+1 สำหรับส่วนที่สองของคำตอบของคุณ คำหลักจำนวนมากมีความหมายที่ไม่สำคัญ คือvolatileเพื่อให้ง่ายต่อการเข้าใจ? หรือfinal? Meh
einpoklum

OTOH, Java ได้รับการออกแบบมาเพื่อใช้งานคุณสมบัติที่ไม่สำคัญเหล่านั้นให้น้อยที่สุด และฉันไม่ได้บอกว่าพวกเขาบรรลุเป้าหมายนั้น (หรือ Java นั้นไม่ได้ลอยไปจากเป้าหมายนั้น) แต่ไม่รวมด้วยเหตุผลนั้นอาจยังมีบุญอยู่ การที่มีสิ่งที่ซับซ้อนอื่น ๆ คือเหตุผลที่ไม่แนะนำเพิ่มเติม (หรือคุณจะต้องจบด้วยภาษา D)
Maarten Bodewes

7

const ใน C ++ ไม่ได้หมายความว่าค่าเป็นค่าคงที่

const ใน C ++ หมายความว่าลูกค้าของสัญญารับรองว่าจะไม่เปลี่ยนแปลงมูลค่าของมัน

ไม่ว่าค่าของconstการเปลี่ยนแปลงการแสดงออกจะเห็นได้ชัดขึ้นถ้าคุณอยู่ในสภาพแวดล้อมที่รองรับการทำงานพร้อมกันตามกระทู้

เนื่องจาก Java ถูกออกแบบมาตั้งแต่เริ่มต้นเพื่อรองรับเธรดและล็อกการทำงานพร้อมกันมันไม่ได้เพิ่มความสับสนโดยการใช้คำมากเกินไปเพื่อให้มีความหมายที่finalมี

เช่น:

#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;
}

ออก 42 แล้ว 7

แม้ว่าการxทำเครื่องหมายว่าconstเป็นนามแฝงที่ไม่ใช่ const จะถูกสร้างขึ้น แต่xก็ไม่ได้เป็นค่าคงที่ ไม่ใช่คอมไพเลอร์ทุกคนต้องการvolatileพฤติกรรมนี้ (แม้ว่าคอมไพเลอร์ทุกคนจะได้รับอนุญาตให้อินไลน์ค่าคงที่)

ด้วยระบบที่ซับซ้อนมากขึ้นคุณจะได้นามแฝงแบบ const / non-const โดยไม่ต้องใช้const_castดังนั้นให้คิดว่า const หมายความว่าบางสิ่งจะไม่เปลี่ยนไปกลายเป็นอันตรายมากขึ้นเรื่อย ๆ constเพียงหมายความว่ารหัสของคุณไม่สามารถเปลี่ยนแปลงได้หากไม่ส่งสัญญาณไม่ใช่ค่าคงที่


3
const int x = 42; - x เป็นค่าคงที่

2
@Neil หากคุณมีออบเจ็กต์หรือตัวแปรหนึ่งชื่อแทนทั้งพอยน์เตอร์แบบ const และ non-const ดังนั้นค่าของ alias แบบ const สามารถเปลี่ยนได้โดย non-const alias ดังนั้นconstไม่ได้หมายความว่าค่าคงที่ หมายความว่าลูกค้าของค่าถูก จำกัด ไม่ให้กลายพันธุ์ ในตัวอย่างของคุณไม่มีนามแฝงดังนั้นผู้ใช้ทั้งหมดจะอยู่ภายใต้ข้อ จำกัด เดียวกัน นี่ไม่ใช่กรณีทั่วไป constส่งผลกระทบต่อลูกค้าไม่ใช่ค่า - มันบอกว่าคุณไม่สามารถเปลี่ยนได้ไม่ว่ามันจะไม่เปลี่ยนแปลง
Pete Kirkham

1
Const-ความถูกต้องเป็นเรื่องเกี่ยวกับสิ่งที่โปรแกรมเมอร์ควรทำไม่สิ่งที่พวกเขา สามารถทำได้ ฉันคิดว่าคุณทุกคนดูเหมือนจะมีจุดนั้น เพียงแค่ต้องการเพิ่มสองสามเซ็นต์ที่อาจเป็นที่สนใจของผู้อ่านเชิงสาเหตุ: รูปแบบการออกแบบเช่นimmutable interfaceและimmutable objectเป็นอีกวิธีหนึ่ง (เอาชนะกับนักแสดงและการสะท้อน) เพื่อเลียนแบบ const ใน Java "True" const สามารถทำได้ด้วยSealedObjectแต่ก็เป็นการทำลายกรณีการใช้งานของวัตถุของเรา
Martin Andersson

6
หนึ่งควรทราบว่าผลลัพธ์ของโปรแกรมของคุณไม่ได้กำหนด const_cast ไม่ได้มีการเปลี่ยนแปลงตัวแปร const มันอยู่ที่นั่นเพื่อส่งผ่านตัวแปร const ไปยัง API ที่ไม่ถูกต้อง const แต่ยังไม่ได้ปรับเปลี่ยนค่า ฉันคิดว่านิสัยในการคิดว่าสิ่งที่ const ไม่เปลี่ยนแปลงนั้นเป็นสิ่งที่ดีเพราะถ้าพวกเขาเปลี่ยนแปลงนั่นหมายถึงโปรแกรมของคุณมีแฮ็กที่อาจแตกได้ตลอดเวลาขึ้นอยู่กับคอมไพเลอร์ที่ใช้
Cygon

1
การปรับเปลี่ยนค่าที่เกิดเป็นค่าคงเป็นพฤติกรรมที่ไม่ได้กำหนด ดิสก์ของคุณอาจฟอร์แมตแล้ว
Zhe Yang

5

นี่เป็นคำถามเก่า ๆ แต่ฉันคิดว่าฉันจะสนับสนุน 2 เซ็นต์ของฉันต่อไปตั้งแต่กระทู้นี้มาในการสนทนาวันนี้

นี่ไม่ได้ตอบว่าทำไมไม่มี const? แต่วิธีการที่จะทำให้การเรียนของคุณไม่เปลี่ยนรูป (น่าเสียดายที่ฉันมีชื่อเสียงไม่มากพอที่จะโพสต์เป็นความคิดเห็นต่อคำตอบที่ยอมรับได้)

วิธีที่จะรับประกันการเปลี่ยนแปลงไม่ได้บนวัตถุคือการออกแบบชั้นเรียนของคุณอย่างระมัดระวังมากขึ้นเพื่อไม่เปลี่ยนรูป สิ่งนี้ต้องการความระมัดระวังมากกว่าคลาสที่ไม่แน่นอน

สิ่งนี้จะกลับไปที่รายการJava ที่มีประสิทธิภาพ ของ Josh Bloch 15 - ความไม่แน่นอนลดลง หากคุณยังไม่ได้อ่านหนังสือเล่มนี้รับสำเนาและอ่านมันไปไม่กี่ครั้งผมกล้ารับประกันว่ามันจะขึ้นเป็นรูปเป็นร่างของคุณ"java เกม"

ในรายการที่ 15 Bloch แนะนำว่าคุณควร จำกัด ความไม่แน่นอนของคลาสเพื่อให้แน่ใจว่าสถานะของวัตถุ

หากต้องการอ้างอิงหนังสือโดยตรง:

คลาสที่ไม่เปลี่ยนรูปเป็นเพียงคลาสที่อินสแตนซ์ที่ไม่สามารถแก้ไขได้ ข้อมูลทั้งหมดที่มีอยู่ในแต่ละอินสแตนซ์ถูกจัดเตรียมไว้เมื่อมันถูกสร้างขึ้นและได้รับการแก้ไขสำหรับอายุการใช้งานของวัตถุ ไลบรารีแพลตฟอร์ม Java ประกอบด้วยคลาสที่ไม่เปลี่ยนรูปได้จำนวนมากรวมถึง String คลาสดั้งเดิมที่มีกล่องและ BigInteer และ BigDecimal มีเหตุผลที่ดีมากมายสำหรับสิ่งนี้: คลาสที่ไม่เปลี่ยนรูปนั้นง่ายต่อการออกแบบใช้งานและใช้งานมากกว่าคลาสที่ไม่แน่นอน พวกเขามีแนวโน้มน้อยที่จะเกิดข้อผิดพลาดและมีความปลอดภัยมากขึ้น

จากนั้น Bloch อธิบายวิธีทำให้คลาสของคุณไม่เปลี่ยนรูปโดยทำตาม 5 กฎง่ายๆ:

  1. ไม่ได้ให้วิธีการใด ๆ ที่ปรับเปลี่ยนสถานะของวัตถุ (เช่น setters, aka mutators )
  2. ตรวจสอบให้แน่ใจว่าไม่สามารถขยายชั้นเรียนได้ (ซึ่งหมายถึงการประกาศชั้นเรียนด้วยตนเองfinal)
  3. finalทำให้ทุกสาขา
  4. privateทำให้ทุกสาขา
  5. ตรวจสอบให้แน่ใจว่ามีการเข้าถึงส่วนประกอบที่เปลี่ยนแปลงได้ไม่ได้ (โดยการทำสำเนาของวัตถุป้องกัน)

สำหรับรายละเอียดเพิ่มเติมฉันขอแนะนำให้เก็บสำเนาหนังสือ


3
const ใน C ++ นั้นมีความยืดหยุ่นมากกว่าการเปลี่ยนไม่ได้เต็มรูปแบบ ในความหมาย 'const' สามารถมองเห็นว่า 'ไม่เปลี่ยนรูปในบริบทนี้' ตัวอย่าง: ฉันมีคลาสที่ไม่เปลี่ยนรูป แต่ฉันต้องการให้แน่ใจว่าไม่ได้มีการแก้ไขผ่าน API สาธารณะที่แน่นอน การสร้างอินเทอร์เฟซ (และส่งคืนสำหรับ API สาธารณะนั้น) ตามที่ Gunslinger47 แนะนำให้ทำในสิ่งเดียวกันใน Java แต่เด็ก - มันน่าเกลียด (และอื่น ๆ - มันถูกเพิกเฉยโดยนักพัฒนา Java ส่วนใหญ่ .
No-Bugs Hare

3

ความหมายของ C ++ constนั้นแตกต่างจาก Java finalอย่างมาก หากผู้ออกแบบใช้constมันจะทำให้สับสนโดยไม่จำเป็น

ความจริงที่ว่าconstเป็นคำที่สงวนไว้แสดงให้เห็นว่านักออกแบบมีแนวคิดในการนำไปใช้constแต่พวกเขาตัดสินใจตั้งแต่นั้นมา ดูข้อผิดพลาดที่ปิดนี้ เหตุผลที่ระบุรวมถึงการเพิ่มการรองรับสไตล์ C ++ constจะทำให้เกิดปัญหาความเข้ากันได้


-1

มีวิธีการสร้างตัวแปร "const" ใน Java แต่สำหรับคลาสที่ระบุเท่านั้น เพียงกำหนดคลาสที่มีคุณสมบัติสุดท้ายและซับคลาสนั้น จากนั้นใช้คลาสฐานที่คุณต้องการใช้ "const" ในทำนองเดียวกันหากคุณต้องการใช้วิธีการ "const" ให้เพิ่มลงในคลาสฐาน คอมไพเลอร์จะไม่อนุญาตให้คุณแก้ไขสิ่งที่คิดว่าเป็นวิธีสุดท้ายของคลาสพื้นฐาน แต่จะอ่านและเรียกเมธอดบนคลาสย่อย


คุณช่วยยกตัวอย่างเรื่องนี้ได้ไหม
NO_NAME

คลาส MYString ใช้ GetString {สตริงสุดท้ายส่วนตัว aaaa; ประชาชน String getString (); } class MutableString ใช้ GetString {String ส่วนตัว aaaa2; ประชาชน String getString (); ประชาชน String setString ()}
user1122069

-2

จะมีสองวิธีในการกำหนดค่าคงที่ - constและstatic finalด้วยความหมายเดียวกันแน่นอน นอกจากนี้static finalอธิบายพฤติกรรมที่ดีกว่าconst


@Bozho คุณพูดว่าพฤติกรรมที่ดีกว่า Const มันเป็นอย่างไร คุณสามารถแบ่งปันตัวอย่างได้
ไหม

ดีตัวแปรคือstatic(ไม่ได้เป็นของอินสแตนซ์เฉพาะ) และfinal- ไม่สามารถเปลี่ยนแปลงได้
Bozho

-2

คุณสามารถใช้ static final เพื่อสร้างบางสิ่งที่ทำงานคล้ายกับ Const ฉันเคยใช้สิ่งนี้ในอดีต

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;

ลดลงสำหรับการเพิ่มประสิทธิภาพตามข่าวลือเพราะฉันได้ยินข่าวลือว่านี่เป็นกลยุทธ์ที่ไม่มีประสิทธิภาพ
afarley

ฉันลบข่าวลือออกจากคำตอบ คุณยังสามารถใช้ int สุดท้ายคงที่เพื่อสร้างรหัสลักษณะ const
hamish

ตกลงฉันลบคะแนนโหวตของฉันแล้ว บางที downvote อื่น ๆ บางอันเกี่ยวกับคำสั่ง switch (มันเกี่ยวข้องอะไรกับตัวอย่างที่เหลือของคุณ?)
4324

ในคำสั่งเปลี่ยนฉันใช้ cRPM ราวกับว่ามันเป็น const ค่อนข้างถูกต้องพิจารณาข้างต้น ใช่ฉันถอดสวิทช์ออกแล้ว
hamish
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.