ทำไมการรันโค้ด Java ในความคิดเห็นที่มีอักขระ Unicode บางตัวอนุญาต


1356

รหัสต่อไปนี้สร้างผลลัพธ์ "Hello World!" (ไม่จริงลองดู)

public static void main(String... args) {

   // The comment below is not a typo.
   // \u000d System.out.println("Hello World!");
}

เหตุผลนี้คือคอมไพเลอร์ Java วิเคราะห์อักขระ Unicode \u000dเป็นบรรทัดใหม่และได้รับการแปลงเป็น:

public static void main(String... args) {

   // The comment below is not a typo.
   //
   System.out.println("Hello World!");
}

จึงส่งผลให้ความคิดเห็นถูก "ดำเนินการ"

ตั้งแต่นี้สามารถใช้เพื่อ "ซ่อน" รหัสที่เป็นอันตรายหรือสิ่งที่โปรแกรมเมอร์ชั่วร้ายสามารถเข้าใจได้ทำไมมันได้รับอนุญาตในการแสดงความคิดเห็น ?

ทำไมสิ่งนี้ถึงได้รับอนุญาตจากข้อกำหนดของ Java?


44
"ทำไมจึงได้รับอนุญาตนี้" ดูเหมือนว่าจะเป็นไปตามความคิดเห็นของฉัน นักออกแบบภาษาได้ตัดสินใจแล้วต้องรู้อะไรอีกบ้าง หากคุณไม่พบคำแถลงของบุคคลที่ตัดสินใจเราสามารถเก็งกำไรได้
Ingo Bürk

194
สิ่งหนึ่งที่น่าสนใจก็คืออย่างน้อยที่OP ของ IDE เห็นได้ชัดว่าได้รับมันไม่ถูกต้องและการแสดงไฮไลต์ที่ไม่ถูกต้อง
dhke

14
อาจเกี่ยวข้องกับ: stackoverflow.com/questions/4448180/…
dhke

47
@Tobb แต่นักออกแบบ Java กำลังเยี่ยมชมดังนั้นจึงเป็นไปได้ที่จะได้รับคำตอบจากหนึ่งในนั้น พวกเขาอาจมีทรัพยากรที่ตอบคำถามนี้แล้ว
Pshemo

41
คำตอบง่ายๆคือรหัสไม่ได้อยู่ในความคิดเห็นเลยตามกฎของภาษาดังนั้นคำถามจึงไม่ถูกต้อง
user207421

คำตอบ:


741

การถอดรหัส Unicode เกิดขึ้นก่อนการแปลคำอื่น ๆ ประโยชน์ที่สำคัญของสิ่งนี้คือมันทำให้ไม่สามารถย้อนกลับไปมาระหว่าง ASCII และการเข้ารหัสอื่น ๆ ได้ คุณไม่จำเป็นต้องคิดออกว่าความเห็นเริ่มต้นและสิ้นสุดอย่างไร!

ตามที่ระบุไว้ในส่วน JLS 3.3สิ่งนี้อนุญาตให้เครื่องมือที่ใช้ ASCII ประมวลผลไฟล์ต้นฉบับ:

[... ] ภาษาการเขียนโปรแกรม Java ระบุวิธีมาตรฐานในการแปลงโปรแกรมที่เขียนใน Unicode เป็น ASCII ที่เปลี่ยนโปรแกรมเป็นรูปแบบที่สามารถประมวลผลได้โดยเครื่องมือที่ใช้ ASCII [ ... ]

สิ่งนี้ให้การรับประกันพื้นฐานสำหรับความเป็นอิสระของแพลตฟอร์ม (ความเป็นอิสระของชุดอักขระที่สนับสนุน) ซึ่งเป็นเป้าหมายสำคัญสำหรับแพลตฟอร์ม Java เสมอ

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

มี gotchas มากมายในชุดรูปแบบนี้และJava Puzzlersโดย Joshua Bloch และ Neal Gafter รวมตัวแปรต่อไปนี้:

นี่เป็นโปรแกรม Java ที่ถูกกฎหมายหรือไม่ ถ้าเป็นเช่นนั้นมันจะพิมพ์อะไร

\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020\u0020
\u0063\u006c\u0061\u0073\u0073\u0020\u0055\u0067\u006c\u0079
\u007b\u0070\u0075\u0062\u006c\u0069\u0063\u0020\u0020\u0020
\u0020\u0020\u0020\u0020\u0073\u0074\u0061\u0074\u0069\u0063
\u0076\u006f\u0069\u0064\u0020\u006d\u0061\u0069\u006e\u0028
\u0053\u0074\u0072\u0069\u006e\u0067\u005b\u005d\u0020\u0020
\u0020\u0020\u0020\u0020\u0061\u0072\u0067\u0073\u0029\u007b
\u0053\u0079\u0073\u0074\u0065\u006d\u002e\u006f\u0075\u0074
\u002e\u0070\u0072\u0069\u006e\u0074\u006c\u006e\u0028\u0020
\u0022\u0048\u0065\u006c\u006c\u006f\u0020\u0077\u0022\u002b
\u0022\u006f\u0072\u006c\u0064\u0022\u0029\u003b\u007d\u007d

(โปรแกรมนี้กลายเป็นโปรแกรม "Hello World" ธรรมดา)

ในการแก้ปัญหาของปริศนาพวกเขาชี้ให้เห็นสิ่งต่อไปนี้:

ยิ่งไปกว่านั้นปริศนานี้ทำหน้าที่เสริมบทเรียนของสามบทก่อนหน้า: การหลบหนีของ Unicode นั้นเป็นสิ่งจำเป็นเมื่อคุณจำเป็นต้องแทรกตัวละครที่ไม่สามารถนำเสนอด้วยวิธีอื่นใดในโปรแกรมของคุณ หลีกเลี่ยงพวกเขาในกรณีอื่นทั้งหมด


แหล่งที่มา: Java: รหัสการดำเนินการในความคิดเห็น?!


84
ในระยะสั้นแล้ว Java จงใจอนุญาต: "ข้อผิดพลาด" อยู่ใน IDE ของ OP หรือไม่
Bathsheba

60
@Bathsheba: มันมีมากขึ้นในหัวของคน ผู้คนไม่พยายามที่จะเข้าใจวิธีการแยกวิเคราะห์ Java ทำงานดังนั้นบางครั้ง IDEs แสดงรหัสในทางที่ผิด ในตัวอย่างด้านบนความคิดเห็นควรลงท้ายด้วย\u000dและส่วนที่ควรมีไฮไลต์รหัส
Aaron Digulla

62
ข้อผิดพลาดทั่วไปอีกประการหนึ่งคือการวางเส้นทาง Windows ในรหัสเช่นเดียวกับ// C:\user\...ที่นำไปสู่ข้อผิดพลาดในการรวบรวมเนื่องจาก\userไม่ใช่ลำดับการหลบหนี Unicode ที่ถูกต้อง
Aaron Digulla

50
ในคราสรหัสหลังจาก\u000dถูกเน้นบางส่วน หลังจากกด Ctrl + Shift + F อักขระจะถูกแทนที่ด้วยบรรทัดใหม่และส่วนที่เหลือของบรรทัดจะถูกห่อ
bluelDe

20
@TheLostMind หากฉันเข้าใจคำตอบอย่างถูกต้องคุณควรจะทำซ้ำสิ่งนี้ด้วยความคิดเห็นบล็อกเช่นกัน \u002A/ควรจบความคิดเห็น
Taemyr

141

เนื่องจากสิ่งนี้ยังไม่ได้รับการแก้ไขนี่เป็นคำอธิบายว่าทำไมการแปลของ Unicode escapes เกิดขึ้นก่อนการประมวลผลซอร์สโค้ดอื่น ๆ :

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

ดังนั้นซอร์สโค้ด Java สามารถเขียนในการเข้ารหัสใด ๆ และอนุญาตให้มีความหลากหลายของตัวละครภายในตัวระบุตัวอักษรและStringตัวอักษรและความคิดเห็น จากนั้นเพื่อที่จะถ่ายโอนโดยไม่สูญเสียอักขระทั้งหมดที่ไม่สนับสนุนการเข้ารหัสเป้าหมายจะถูกแทนที่ด้วย Unicode escapes

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

นี่คือเหตุผลสำหรับฟีเจอร์แปลก ๆ ที่ไม่ได้กล่าวถึง: \uuuuuuxxxxไวยากรณ์:

เมื่อเครื่องมือแปลเป็นตัวอักษรและหลบหนีพบลำดับที่มีอยู่แล้วลำดับหนีก็ควรใส่เพิ่มอีกuเป็นลำดับแปลงไป\ucafe \uucafeความหมายไม่เปลี่ยนแปลง แต่เมื่อแปลงไปในทิศทางอื่นเครื่องมือควรลบเพียงหนึ่งuและแทนที่ลำดับเท่านั้นที่มีuอักขระ Unicode เดียว ด้วยวิธีนี้แม้แต่ Unicode escapes ยังคงอยู่ในรูปแบบดั้งเดิมเมื่อทำการแปลงไปมา ฉันเดาว่าไม่มีใครเคยใช้คุณสมบัตินี้ ...


1
ที่น่าสนใจnative2asciiดูเหมือนว่าจะไม่ใช้\uu...xxxxไวยากรณ์
ninjalj

5
ใช่native2asciiมีวัตถุประสงค์เพื่อช่วยเตรียมการรวมกลุ่มทรัพยากรโดยแปลงเป็น iso-latin-1 ตามที่Properties.loadได้รับการแก้ไขให้อ่าน latin-1 เท่านั้น และมีกฎแตกต่างกันไม่มี\uuu…ไวยากรณ์และไม่มีขั้นตอนการประมวลผลก่อน ในไฟล์คุณสมบัติเป็นที่แน่นอนเช่นเดียวกับproperty=multi\u000aline property=multi\nline(ขัดแย้งกับวลี“ การใช้ Unicode Escape ตามที่กำหนดในส่วน 3.3 ของข้อกำหนดภาษา Java ™” ของเอกสาร)
Holger

10
โปรดทราบว่าเป้าหมายการออกแบบนี้สามารถบรรลุได้หากไม่มีหูด วิธีที่ง่ายที่สุดคือห้ามการ\uหลบหนีเพื่อสร้างตัวละครในช่วง U + 0000–007F (ตัวละครดังกล่าวทั้งหมดสามารถแสดงได้โดยกำเนิดจากการเข้ารหัสระดับชาติทั้งหมดที่เกี่ยวข้องในปี 1990- ดีอาจยกเว้นอักขระควบคุมบางตัว แต่คุณไม่ต้องการให้เขียน Java ต่อไป)
zwol

3
@zwol: ดีถ้าคุณแยกตัวควบคุมที่ไม่ได้รับอนุญาตภายในซอร์สโค้ด Java คุณก็ถูกต้อง อย่างไรก็ตามมันจะบ่งบอกถึงการสร้างกฎที่ซับซ้อนมากขึ้น และวันนี้มันก็สายเกินไปที่จะพูดคุยเกี่ยวกับการตัดสินใจ ...
โฮลเจอร์

อาปัญหาของการบันทึกเอกสารใน utf8 ไม่ใช่ภาษาละตินหรืออย่างอื่น ฐานข้อมูลทั้งหมดของฉันถูกทำลายเช่นกันเนื่องจากเรื่องไร้สาระตะวันตกนี้
เดวิด天宇วงศ์

106

ฉันจะเพิ่มจุดโดยไม่ได้ผลอย่างสมบูรณ์เพียงเพราะฉันไม่สามารถช่วยตัวเองและฉันยังไม่ได้เห็นว่าคำถามนั้นไม่ถูกต้องเนื่องจากมันมีหลักฐานที่ซ่อนอยู่ซึ่งผิดนั่นคือรหัสอยู่ใน ความคิดเห็น!

ในซอร์สโค้ด Java \ u000d เทียบเท่าในทุก ๆ ทางกับอักขระ ASCII CR มันเป็นจุดสิ้นสุดของเส้นเรียบง่ายและเรียบง่ายไม่ว่ามันจะเกิดขึ้นที่ไหนก็ตาม การจัดรูปแบบในคำถามทำให้เข้าใจผิดว่าจริง ๆ แล้วลำดับของอักขระที่สอดคล้องกับ syntactically คือ:

public static void main(String... args) {
   // The comment below is no typo. 
   // 
 System.out.println("Hello World!");
}

IMHO คำตอบที่ถูกต้องที่สุดคือ: รหัสดำเนินการเพราะมันไม่ได้อยู่ในความคิดเห็น; มันอยู่ในบรรทัดถัดไป ไม่อนุญาตให้ใช้ "การเรียกใช้โค้ดในความคิดเห็น" ใน Java เช่นเดียวกับที่คุณคาดไว้

ความสับสนส่วนใหญ่เกิดจากข้อเท็จจริงที่ว่าปากกาเน้นข้อความไวยากรณ์และ IDE ไม่ซับซ้อนพอที่จะพิจารณาสถานการณ์นี้ พวกเขาอาจไม่ดำเนินการหนี Unicode ที่ทั้งหมดหรือพวกเขาทำมันหลังจากแยกรหัสแทนก่อนเช่นjavacไม่


6
ฉันยอมรับว่านี่ไม่ใช่จาวา "ข้อผิดพลาดในการออกแบบ" แต่เป็นข้อผิดพลาดของ IDE
bvdb

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

@Phil: ดูเหมือนว่าจะเป็นความคิดเห็นเมื่อดูด้วยเครื่องมือเฉพาะเท่านั้นส่วนอื่น ๆ จะแสดงเป็นอย่างอื่น
jmoreno

1
@jmoreno หนึ่งไม่ควรมีจะมีอะไรมากไปกว่าโปรแกรมแก้ไขข้อความในการอ่านรหัส อย่างน้อยที่สุดก็เป็นการละเมิดหลักการที่ทำให้ประหลาดใจอย่างน้อยนั่นคือ // ความคิดเห็นสไตล์จะดำเนินต่อไปจนถึงอักขระ \ n ตัวถัดไป - ไม่ใช่ลำดับอื่นใดซึ่งท้ายที่สุดแทนที่ด้วย \ n ในที่สุด ความคิดเห็นไม่เคยคาดหวังว่าจะเป็นอย่างอื่น ตัวประมวลผลล่วงหน้าไม่ดี
ฟิล

69

การยกเว้น\u000dจะยุติความคิดเห็นเนื่องจากการ\uแปลงจะถูกแปลงเป็นอักขระ Unicode ที่สอดคล้องกันก่อนที่โปรแกรมจะถูกโทเค็น คุณอย่างเท่าเทียมกันสามารถใช้\u0057\u0057แทนการ//ที่จะเริ่มต้นการแสดงความคิดเห็น

นี่เป็นจุดบกพร่องใน IDE ของคุณซึ่งควรเน้นไวยากรณ์บรรทัดเพื่อให้ชัดเจนว่า\u000dสิ้นสุดความคิดเห็น

นี่เป็นข้อผิดพลาดในการออกแบบในภาษา ไม่สามารถแก้ไขได้ในขณะนี้เพราะจะทำให้โปรแกรมที่ใช้งานไม่ได้ \uescapes ควรถูกแปลงเป็นอักขระ Unicode ที่สอดคล้องกันโดยคอมไพเลอร์เฉพาะในบริบทที่ "เหมาะสม" (สตริงตัวอักษรและตัวระบุและอาจไม่มีที่อื่น) หรือควรห้ามสร้างอักขระในช่วง U + 0000–007F , หรือทั้งคู่. อย่างใดอย่างหนึ่งของความหมายเหล่านั้นจะมีการป้องกันความคิดเห็นจากการถูกยกเลิกโดย\u000dหลบหนีโดยไม่รบกวนกับกรณีที่\uหนีออกมามีประโยชน์ทราบว่ารวมถึงการใช้งานของ\uหนีภายในการแสดงความคิดเห็นเป็นวิธีที่จะแสดงความคิดเห็นในการเข้ารหัสในสคริปต์ที่ไม่ใช่ภาษาละตินเพราะ โปรแกรมแก้ไขข้อความสามารถใช้มุมมองที่กว้างขึ้นของที่\uทางหนีมีความสำคัญกว่าคอมไพเลอร์ไม่ (ฉันไม่ทราบถึงตัวแก้ไขหรือ IDE ใด ๆ ที่จะแสดง\uEscape เป็นอักขระที่เกี่ยวข้องในบริบทใด ๆ )

มีข้อผิดพลาดในการออกแบบที่คล้ายกันในตระกูล C คือ1ซึ่งมีการประมวลผล backslash-newline ก่อนกำหนดขอบเขตความคิดเห็นดังนั้นเช่น

// this is a comment \
   this is still in the comment!

ฉันนำสิ่งนี้ขึ้นมาเพื่อแสดงให้เห็นว่ามันเป็นเรื่องง่ายที่จะทำให้เกิดข้อผิดพลาดในการออกแบบโดยเฉพาะและไม่ได้ตระหนักว่ามันเป็นข้อผิดพลาดจนกว่าจะสายเกินไปที่จะแก้ไขได้ถ้าคุณคุ้นเคยกับการคิดโทเค็น เกี่ยวกับโทเค็นและการแยกวิเคราะห์ โดยทั่วไปถ้าคุณได้กำหนดไวยกรณ์อย่างเป็นทางการแล้วมีใครบางคนมาพร้อมกับกรณีพิเศษเกี่ยวกับวากยสัมพันธ์ - trigraphs, backslash-newline, การเข้ารหัสอักขระ Unicode โดยพลการในไฟล์ต้นฉบับที่ จำกัด ASCII ไม่ว่าจะต้องมีอะไรก็ตาม เพิ่มการแปลงผ่านหน้า tokenizer มากกว่าที่จะกำหนด tokenizer อีกครั้งเพื่อให้ความสนใจกับตำแหน่งที่เหมาะสมในการใช้เคสพิเศษ

1สำหรับคนเดินเท้า: ฉันรู้ว่าแง่มุมของ C นี้เป็นความตั้งใจ 100% โดยมีเหตุผล - ฉันไม่ได้ทำสิ่งนี้ - มันจะช่วยให้คุณใส่รหัสเชิงกลโดยใช้กลไกที่มีเส้นยาวโดยไม่ตั้งใจลงบนการ์ดที่ถูกเจาะ มันยังคงเป็นการตัดสินใจออกแบบที่ไม่ถูกต้อง


17
ฉันจะไม่ไปเท่าที่บอกว่ามันเป็นการออกแบบข้อผิดพลาด ฉันเห็นด้วยกับคุณว่ามันเป็นตัวเลือกการออกแบบที่ไม่ดีหรือเป็นทางเลือกที่มีผลกระทบที่โชคร้าย แต่ฉันก็ยังคิดว่ามันทำงานได้เหมือนนักออกแบบภาษาที่ตั้งใจไว้: มันช่วยให้คุณใช้อักขระ Unicode ได้ทุกที่ในไฟล์ ของไฟล์
aioobe

12
ที่ได้รับการกล่าวว่าฉันคิดว่าทางเลือกของขั้นตอนการประมวลผลสำหรับ\uไร้สาระน้อยกว่าการตัดสินใจที่จะปฏิบัติตามนำของ C ในการใช้ศูนย์นำสำหรับสัญกรณ์แปด แม้ว่าสัญกรณ์เลขฐานแปดจะมีประโยชน์บางครั้งฉันยังไม่ได้ยินใครเลยที่โต้แย้งว่าทำไมศูนย์นำหน้าจึงเป็นวิธีที่ดีในการบ่งชี้
supercat

3
@supercat ผู้ที่ขว้างคุณลักษณะนั้นลงใน C89 นั้นกำลังสรุปพฤติกรรมของตัวประมวลผลล่วงหน้า K&R ดั้งเดิมแทนที่จะออกแบบคุณลักษณะตั้งแต่เริ่มต้น ฉันสงสัยว่าพวกเขาคุ้นเคยกับแนวทางปฏิบัติที่ดีที่สุดของบัตรเจาะและฉันยังสงสัยว่าคุณลักษณะนี้เคยถูกใช้เพื่อจุดประสงค์ที่ระบุไว้ยกเว้นอาจเป็นแบบฝึกหัด retrocomputing หนึ่งหรือสองแบบ
zwol

8
@supercat ฉันจะไม่มีปัญหากับ Java \uเป็นการแปลงโทเค็นล่วงหน้าหากไม่ได้รับอนุญาตให้สร้างตัวละครในช่วง U + 0000..U + 007F เป็นการรวมกันของ "สิ่งนี้ใช้งานได้ทุกที่" และ "นามแฝงอักขระ ASCII ที่มีนัยสำคัญทางไวยากรณ์" ซึ่งลดระดับความผิดพลาดจากการเกะกะไปจนถึงการแบนผิด
zwol

4
บน "สำหรับ pedants": แน่นอนในเวลานั้นคิดเห็นบรรทัดเดียวไม่ได้อยู่ และเนื่องจาก C มี terminator ข้อความสั่งที่ไม่ใช่บรรทัดใหม่ส่วนใหญ่จึงจะใช้สำหรับสตริงยาวยกเว้นว่าเท่าที่ฉันสามารถระบุได้ว่า "concatenation ของตัวอักษรสตริง" อยู่ที่นั่นจาก K&R //
Mark Hurd

22

นี่เป็นตัวเลือกการออกแบบโดยเจตนาซึ่งย้อนกลับไปสู่การออกแบบดั้งเดิมของ Java

สำหรับผู้ที่ถามว่า "ใครต้องการ Unicode หลบหนีในความคิดเห็น?" ฉันคิดว่าพวกเขาเป็นคนที่ภาษาพื้นเมืองใช้ชุดอักขระละติน กล่าวอีกนัยหนึ่งมันมีอยู่ในการออกแบบดั้งเดิมของ Java ที่ผู้ใช้สามารถใช้อักขระ Unicode ได้ตามที่กฎหมายในโปรแกรม Java โดยทั่วไปมักจะอยู่ในความคิดเห็นและสตริง

มันเป็นข้อบกพร่องในโปรแกรม (เช่น IDEs) ที่ใช้ในการดูข้อความต้นฉบับที่โปรแกรมดังกล่าวไม่สามารถตีความ Unicode หนีและแสดงสัญลักษณ์ที่สอดคล้องกัน


8
ทุกวันนี้เราใช้ UTF-8 สำหรับซอร์สโค้ดของเราและสามารถใช้อักขระ Unicode โดยตรงไม่จำเป็นต้องใช้ Escape
Paŭlo Ebermann

21

ฉันเห็นด้วยกับ @zwol ว่านี่เป็นความผิดพลาดในการออกแบบ แต่ฉันยิ่งสำคัญกว่า

\uการหลบหนีมีประโยชน์ในสตริงและตัวอักษรถ่าน; และนั่นเป็นสถานที่เดียวที่ควรมีอยู่ มันควรได้รับการจัดการในลักษณะเดียวกับการหลบหนีอื่น ๆ เช่น\n; และ"\u000A" ควรหมายถึงอย่างแน่นอน"\n"หมายถึงว่า

ไม่มีประเด็นที่จะมีอย่างแน่นอน \uxxxxในการแสดงความคิดเห็น - ไม่มีใครสามารถอ่านได้

ในทำนองเดียวกันไม่มีจุดใช้ \uxxxxในส่วนอื่นของโปรแกรม อาจมีข้อยกเว้นเพียงอย่างเดียวใน API สาธารณะที่มีการบังคับให้มีตัวอักษรที่ไม่ใช่ ASCII - ครั้งล่าสุดที่เราเห็นคืออะไร

นักออกแบบมีเหตุผลในปี 1995 แต่ 20 ปีต่อมาสิ่งนี้ดูเหมือนจะเป็นทางเลือกที่ผิด

(คำถามกับผู้อ่าน - ทำไมคำถามนี้ยังคงได้รับคะแนนใหม่หรือไม่คำถามนี้เชื่อมโยงจากที่ใดที่หนึ่งเป็นที่นิยม?)


5
ฉันเดาว่าคุณไม่ได้ไปไหนมาไหนโดยใช้อักขระที่ไม่ใช่ ASCII ใน API มีคนใช้ (ไม่ใช่ฉัน) เช่นในประเทศแถบเอเชีย และเมื่อคุณใช้อักขระที่ไม่ใช่ ASCII ในตัวระบุห้ามการอ้างอิงในความคิดเห็นเอกสารมีเหตุผลเล็กน้อย อย่างไรก็ตามการอนุญาตให้พวกเขาอยู่ในโทเค็นและช่วยให้พวกเขาเปลี่ยนความหมายหรือขอบเขตของโทเค็นเป็นสิ่งที่แตกต่างกัน
Holger

15
พวกเขาสามารถใช้การเข้ารหัสไฟล์ที่เหมาะสม ทำไมเขียนint \u5431เมื่อคุณสามารถทำได้int 整
ZhongYu

3
คุณจะทำอย่างไรเมื่อคุณต้องคอมไพล์โค้ดกับ API และไม่สามารถใช้การเข้ารหัสที่เหมาะสม (สมมติว่าไม่มีการUTF-8สนับสนุนอย่างกว้างขวางในปี 1995) คุณเพียงแค่ต้องเรียกวิธีการอย่างใดอย่างหนึ่งและไม่ต้องการที่จะติดตั้งชุดสนับสนุนภาษาเอเชียของระบบปฏิบัติการ (จำยุค) สำหรับวิธีการเดียวที่ ...
โฮล

5
อะไรคือสิ่งที่ชัดเจนกว่าปี 1995 คือคุณจะรู้ภาษาอังกฤษได้ดีกว่าถ้าคุณต้องการโปรแกรม การเขียนโปรแกรมเป็นการโต้ตอบระหว่างประเทศและทรัพยากรเกือบทั้งหมดเป็นภาษาอังกฤษ
ZhongYu

8
ฉันไม่คิดว่ามันจะเปลี่ยนไป เอกสารภาษาจาวาเป็นภาษาอังกฤษเกือบทุกครั้งเช่นกัน มีการแปลภาษาญี่ปุ่นเป็นระยะเวลาหนึ่ง แต่การบำรุงรักษาสองภาษาไม่ได้เป็นการสำรองข้อมูลความคิดในการรักษาไว้สำหรับสถานที่ทั้งหมดของโลก (ค่อนข้างหักล้าง) และก่อนหน้านั้นไม่มีภาษากระแสหลักที่สนับสนุน Unicode ในตัวระบุอยู่ดี ดังนั้นฉันเดาบางคนคิดว่าซอร์สโค้ดที่แปลเป็นเรื่องใหญ่ต่อไป ฉันจะบอกว่าโชคดีที่มันไม่ได้ถอด
Holger

11

มีเพียงคนเดียวที่สามารถตอบได้ว่าเหตุใด Unicode จึงถูกนำมาใช้เนื่องจากพวกเขาเป็นคนที่เขียนข้อกำหนด

เหตุผลที่เป็นไปได้สำหรับเรื่องนี้คือมีความปรารถนาที่จะอนุญาตให้ BMP ทั้งหมดเป็นอักขระที่เป็นไปได้ของซอร์สโค้ด Java สิ่งนี้นำเสนอปัญหา:

  • คุณต้องการที่จะใช้อักขระ BMP ใด ๆ
  • คุณต้องการที่จะสามารถป้อน BMP charater ใด ๆ ได้ง่ายพอสมควร วิธีการทำเช่นนี้คือการหลบหนี Unicode
  • คุณต้องการทำให้ข้อกำหนดทางศัพท์ง่ายสำหรับมนุษย์ในการอ่านและเขียนและง่ายต่อการใช้เช่นกัน

นี่เป็นเรื่องยากอย่างเหลือเชื่อเมื่อ Unicode หนีเข้าสู่การต่อสู้: มันสร้างกฎ lexer ใหม่ทั้งหมด

วิธีที่ง่ายที่สุดคือการทำสองขั้นตอนคือการค้นหาครั้งแรกและแทนที่ Unicode ทั้งหมดด้วยอักขระที่มันแทนแล้วแยกวิเคราะห์เอกสารที่เป็นผลลัพธ์ราวกับว่า Unicode Escape ไม่มีอยู่

ข้อดีของมันก็คือมันง่ายที่จะระบุดังนั้นมันจึงทำให้สเปคนั้นง่ายขึ้นและง่ายต่อการใช้งาน

ข้อเสียก็คือตัวอย่างของคุณ


2
หรือ จำกัด การใช้ \ uxxxx เฉพาะตัวระบุสตริงตัวอักษรและค่าคงที่ของอักขระ สิ่งใดที่ C11 ทำ
ninjalj

ที่ทำให้กฎ parser ซับซ้อนจริง ๆ เพราะนั่นคือสิ่งที่กำหนดสิ่งเหล่านั้นซึ่งเป็นสิ่งที่ฉันคาดเดาเป็นส่วนหนึ่งของเหตุผลว่ามันเป็นวิธีที่มันเป็น
Martijn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.