ข้อมูลจำเพาะหมายเลข L (ยาว) ของ Java


97

ดูเหมือนว่าเมื่อคุณพิมพ์ตัวเลขใน Java คอมไพลเลอร์จะอ่านเป็นจำนวนเต็มโดยอัตโนมัติซึ่งเป็นเหตุผลว่าทำไมเมื่อคุณพิมพ์ (long) 6000000000(ไม่อยู่ในช่วงของจำนวนเต็ม) มันจะบ่นว่า6000000000ไม่ใช่จำนวนเต็ม 6000000000Lการแก้ไขปัญหานี้ผมต้องระบุ ฉันเพิ่งเรียนรู้เกี่ยวกับสเปคนี้

มีข้อกำหนดตัวเลขอื่น ๆ เช่นสั้นไบต์ลอยคู่หรือไม่? ดูเหมือนว่าสิ่งเหล่านี้จะดีที่จะมีเพราะ (ฉันถือว่า) ถ้าคุณสามารถระบุหมายเลขที่คุณกำลังพิมพ์เป็นตัวย่อ java ก็ไม่ต้องแคสต์ - นั่นเป็นข้อสันนิษฐานโปรดแก้ไขฉันถ้าฉันผิด . ปกติฉันจะค้นหาคำถามนี้ด้วยตัวเอง แต่ฉันไม่รู้ว่าข้อกำหนดตัวเลขประเภทนี้เรียกว่าอะไร

คำตอบ:


178

มีคำต่อท้ายเฉพาะสำหรับlong(เช่น39832L) float(เช่น2.4f) และdouble(เช่น-7.832d)

หากไม่มีคำต่อท้ายและเป็นประเภทอินทิกรัล (เช่น5623) จะถือว่าเป็นintไฟล์. ถ้าไม่ใช่ประเภทอินทิกรัล (เช่น3.14159) จะถือว่าเป็นกdouble.

ในกรณีอื่น ๆ ( byte, short, char) คุณต้องโยนเป็นไม่มีคำต่อท้ายที่เฉพาะเจาะจง

ข้อมูลจำเพาะ Java ช่วยให้ทั้งบนและล่างต่อท้ายกรณี แต่รุ่นกรณีบนสำหรับlongs เป็นที่ต้องการเป็นกรณีบนLน้อยง่ายต่อการสับสนกับเลขกว่ากรณีที่ต่ำกว่า1l

ดูรายละเอียดเกี่ยวกับเลือดในส่วน JLS 3.10 (ดูคำจำกัดความของIntegerTypeSuffix)


9
รายการกำหนด: ถอดแหล่งที่มีศักยภาพของความคลุมเครืออยู่เสมอที่ดีและผมไม่เห็นด้วย ... แต่ผมเชื่อว่าถ้าคุณพบว่าตัวเองทำให้เกิดความสับสน1กับlและ0มีO(และอื่น ๆ ) ของคุณมีความสำคัญคือการตั้งค่าที่เหมาะสมตัวอักษร (ถ้าคุณสามารถ ) จากนั้นกังวลว่าจะไม่พลาดปุ่ม Shift
davidcesarino

@SimonNickerson ฉันมีคำถามเกี่ยวกับคำต่อท้าย ... ถ้าฉันประกาศตัวแปรlongหรือdoubleเช่น: long _lo = 30;และไม่ได้30Lหมายความว่าตัวแปรของฉันจะถูกแปลงเป็นfloatหรือไม่? หรือในกรณีที่_lo = _lo + 2.77ว่า_loจะมีการออกเสียงลงไปลอยแม้ว่ามันจะถูกประกาศให้เป็นยาว
luigi7up

ไม่ลอยไม่เกี่ยวข้องกับที่นี่ ในกรณีแรก30คือสิ่งintที่ได้รับการแปลงโดยอัตโนมัติผ่านการแปลงที่กว้างขึ้นเป็นlongไฟล์. ในกรณีที่สองคำแถลงของคุณผิดกฎหมาย คุณต้องเหวี่ยงด้านขวามือให้ยาวอย่างชัดเจนเช่น_lo = (long) (_lo + 2.77)
Simon Nickerson

4
@DavidCesarino การเปลี่ยนแบบอักษรจะช่วยแก้ไขความคลุมเครือสำหรับคุณ - ในตัวแก้ไขเฉพาะที่คุณตั้งค่าไว้ถูกต้อง การเปลี่ยน l เป็น L จะแก้ไขความคลุมเครือสำหรับทุกคนที่อาจเคยอ่านโค้ดของคุณรวมถึงตัวคุณเองเมื่อคุณอ่านโค้ดใน Editor อื่น IDE โดยดูที่ซอร์สบนเว็บ (เครื่องมือตรวจสอบที่เก็บ ฯลฯ ) IMHO ลำดับความสำคัญไม่ควรพลาดปุ่ม Shift Btw. คุณแนะนำฟอนต์อะไร ฉันชอบ monospace และเป็นค่าเริ่มต้นเกือบทั้งหมดในบรรณาธิการ CLIs และอื่น ๆ ที่ฉันเห็นและในแบบอักษรนี้lและ1( 0และOresp.) ค่อนข้างคล้ายกัน
dingalapadum

1
@dingalapadum อย่างที่บอกคุณพูดถูก การลบแหล่งที่มาของความไม่ชัดเจนเป็นสิ่งที่ควรทำ ฉันแค่บอกว่าคุณไม่ควรใช้ตัวแก้ไขใด ๆ ที่คุณอาจเข้าใจผิดได้ง่าย กล่าวอีกนัยหนึ่งข้อเสนอแนะเก่า ๆ ในการเข้ารหัสเชิงป้องกัน แต่ไม่ได้ขึ้นอยู่กับมัน เกี่ยวกับฟอนต์มันเป็นเรื่องส่วนตัวมาก แต่ฉันมักจะใช้ Deja Vu Sans Mono ทุกครั้งที่ทำได้เพราะ 1) มันเป็นแบบโมโนสเปซ 2) ไม่มีความคลุมเครือระหว่างตัวละคร และ 3) ฉันชอบรูปทรงที่สวยงามและสง่างามเกือบจะเหมือนกับฟอนต์ sans-serif ที่ดีและอ่านได้ (ฟอนต์การเขียนโปรแกรมที่ดีอื่น ๆ ให้ความรู้สึก "โลหะ" IMHO ด้วย)
davidcesarino

13

ฉันหวังว่าคุณจะไม่สนใจเรื่องสัมผัสเล็กน้อย แต่คิดว่าคุณอาจสนใจที่จะรู้ว่านอกจากF(สำหรับลอย) D(สำหรับคู่) และL(นาน) แล้วยังมีการเสนอให้เพิ่มคำต่อท้ายสำหรับbyteและshort- YและSตามลำดับ . สิ่งนี้จะขจัดความจำเป็นในการส่งเป็นไบต์เมื่อใช้ไวยากรณ์แบบอักษรสำหรับอาร์เรย์ไบต์ (หรือแบบสั้น) อ้างถึงตัวอย่างจากข้อเสนอ:

ประโยชน์ที่สำคัญ: เหตุใดแพลตฟอร์มจึงดีกว่าหากมีการนำข้อเสนอมาใช้

รหัส cruddy เช่น

 byte[] stuff = { 0x00, 0x7F, (byte)0x80,  (byte)0xFF};

สามารถเข้ารหัสเป็นไฟล์

 byte[] ufum7 = { 0x00y, 0x7Fy, 0x80y, 0xFFy };

Joe Darcy ดูแล Project Coin สำหรับ Java 7 และบล็อกของเขาเป็นวิธีง่ายๆในการติดตามข้อเสนอเหล่านี้


คงจะดี ... ฉันพบเสมอว่านักแสดงทุกคนน่ารำคาญจริงๆ
jbu

ฉันใช้มันไม่ได้ทำให้เป็น Java 7 หากมีคำใดที่จะทำให้เป็นการอัปเดตในอนาคตหรือ Java 8?
ขยี้

@crush ฉันพยายามตรวจสอบเมื่อสองสามเดือนก่อนและเท่าที่ฉันสามารถบอกได้ข้อเสนอถูกยกเลิก เราได้รับ _ ในตัวอักษรตัวเลขและ0bคำนำหน้าสำหรับตัวอักษรไบนารีแม้ว่า โห่.
erickson

ข้อเสนอนี้อาจถูกนำไปใช้บน kotlin แทนที่จะเป็น java เนื่องจาก Oracle ไม่ต้องการให้ชุมชนบอกวิธีการทำงาน ... เราอยู่ในปี 2018 และยังไม่มีอะไรเกี่ยวกับข้อเสนอนี้ แต่น่าเศร้า
JoelBonetR

12

โดยค่าเริ่มต้นประเภทข้อมูลไพรเมตอินทิกรัลใด ๆ (ไบต์สั้น int ยาว) จะถือว่าเป็นประเภทintโดยคอมไพเลอร์ java สำหรับไบต์และสั้นตราบเท่าที่ค่าที่กำหนดให้อยู่ในช่วงไม่มีปัญหาและไม่จำเป็นต้องมีส่วนต่อท้าย หากค่าที่กำหนดให้กับไบต์และสั้นเกินช่วงจำเป็นต้องมีการแคสต์ประเภทที่ชัดเจน

เช่น:

byte b = 130; // CE: range is exceeding.

เพื่อเอาชนะการหล่อประเภทนี้

byte b = (byte)130; //valid, but chances of losing data is there.

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

Long l = 2147483647; //which is max value of int

ในกรณีนี้ไม่จำเป็นต้องมีคำต่อท้ายเช่น L / l โดยค่าเริ่มต้น 2147483647 ถือว่าคอมไพเลอร์ java คือประเภท int การหล่อประเภทภายในทำโดยคอมไพเลอร์และ int เลื่อนระดับเป็นประเภทยาวโดยอัตโนมัติ

Long l = 2147483648; //CE: value is treated as int but out of range 

ที่นี่เราต้องใส่คำต่อท้ายเป็น L เพื่อให้ถือว่า 2147483648 ลิเทอรัลเป็นแบบยาวโดยคอมไพเลอร์ java

ในที่สุด

Long l = 2147483648L;// works fine.


1

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

เนื่องจากการแยกวิเคราะห์ตัวอักษรเกิดขึ้นในเวลาคอมไพล์จึงไม่เกี่ยวข้องอย่างยิ่งในเรื่องประสิทธิภาพ เหตุผลเดียวที่มีshortและbyteคำต่อท้ายจะดีก็คือทำให้โค้ดมีขนาดกะทัดรัดมากขึ้น


0

เพื่อให้เข้าใจว่าเหตุใดจึงจำเป็นต้องแยกความแตกต่างระหว่างintและlongตัวอักษรให้พิจารณา:

long l = -1 >>> 1;

เทียบกับ

int a = -1;
long l = a >>> 1;

lตอนนี้เป็นคุณอย่างถูกต้องคาดว่าจะได้ทั้งเศษรหัสให้ค่าเดียวกันกับตัวแปร โดยไม่สามารถแยกแยะintและตามlongตัวอักษรได้การตีความหมายถึง-1 >>> 1อะไร?

-1L >>> 1 // ?

หรือ

(int)-1 >>> 1 // ?

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

นี้ไม่ได้เกิดขึ้นbyte, shortและcharเพราะพวกเขามีการส่งเสริมเสมอก่อนที่จะดำเนินการทางคณิตศาสตร์และค่าที่เหมาะสม เนื้อหาควรเป็นคำต่อท้ายประเภทจำนวนเต็มเพื่อใช้ในการพูดนิพจน์การเริ่มต้นอาร์เรย์ แต่ไม่มี floatใช้คำต่อท้ายfและdouble d. ตัวอักษรอื่น ๆ nullมีชนิดที่ชัดเจนกับการมีชนิดพิเศษสำหรับ


ฉันจะสนใจในสิ่งที่คุณหมายถึงในสมัยก่อน ในทั้งสองกรณีฉันได้รับ 2147483647 และฉันไม่เข้าใจว่าทำไมฉันควรคาดหวังอย่างอื่น
เหลือเชื่อ

@TheincredibleJan คุณจะคาดหวังได้อย่างถูกต้องInteger.MAX_VALUEอย่างไรก็ตามหากไม่มีวิธีแยกความแตกต่างระหว่างintและlongตัวอักษรมันจะคลุมเครือ / ฉันจำคำถามนี้ไม่ได้ แต่ได้ชี้แจงคำตอบของฉันแล้ว
Tom Hawtin - แท็กไลน์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.