2012-03-03 18 views
6

Đặc tả ngôn ngữ Java nói rằng các dấu thoát bên trong các chuỗi là các ký tự C "bình thường" như \n\t, nhưng chúng cũng chỉ định các số bát phân thoát ra khỏi \0 đến \377. Cụ thể, JLS khẳng định:Tại sao lưu thoát bát phân Java chỉ lên tới 255?

OctalEscape: 
    \ OctalDigit 
    \ OctalDigit OctalDigit 
    \ ZeroToThree OctalDigit OctalDigit 

OctalDigit: one of 
    0 1 2 3 4 5 6 7 

ZeroToThree: one of 
    0 1 2 3 

có nghĩa là một cái gì đó giống như \4715 là bất hợp pháp, mặc dù nó được trong phạm vi của một nhân vật Java (Java từ nhân vật không phải là byte).

Tại sao Java có hạn chế tùy ý này? Làm cách nào để xác định mã bát phân cho các ký tự vượt quá 255?

+1

255 là giới hạn ASCII cơ bản nếu tôi không nhầm bạn có một cho mỗi ký tự ASCII cơ sở duy nhất. Bạn có nên hạnh phúc với điều đó không? Lý do bạn không thể đi tới, nói rằng \ 4715 đơn giản là vì nó vượt quá 255 là giới hạn ASCII chuẩn = D (Tôi không hiểu giải thích, hãy tham khảo người trả lời) –

+1

@Shingetsu: giới hạn ASCII là 127, không phải 255 _Bytes_ được giới hạn ở 255, trừ khi bạn đang nói về các byte Java, vì một số lý do kỳ lạ, đã ký :-) Nhưng các ký tự Java không phải là byte. – paxdiablo

+0

[Xem thêm] (http://stackoverflow.com/questions/3537706/howto-unescape-a-java-string-literal-in-java/4298836) –

Trả lời

9

Nó có lẽ là cho lý do lịch sử hoàn toàn là Java hỗ trợ chuỗi thoát bát phân. Các trình tự thoát này bắt nguồn từ C (hoặc có thể là tiền nhiệm của B và BCPL), trong những ngày mà các máy tính như PDP-7 cai trị Trái đất, và nhiều lập trình được thực hiện trong lắp ráp hoặc trực tiếp trong mã máy, và bát phân là số ưa thích cơ sở để viết mã lệnh, và không có Unicode, chỉ ASCII, vì vậy ba số bát phân đủ để đại diện cho toàn bộ bộ ký tự.

Khi Unicode và Java xuất hiện, bát phân có nhiều cách được đưa ra thập lục phân làm cơ sở số được ưu tiên khi số thập phân không thực hiện được. Vì vậy, Java có chuỗi thoát \u có các chữ số thập lục phân. Trình tự thoát bát phân có lẽ chỉ được hỗ trợ để làm cho các lập trình viên C trở nên thoải mái, và để dễ dàng sao chép các hằng số chuỗi từ các chương trình C vào các chương trình Java.

Kiểm tra những liên kết này để đố lịch sử:

http://en.wikipedia.org/wiki/Octal#In_computers
http://en.wikipedia.org/wiki/PDP-11_architecture#Memory_management

+1

+1 Cũng lưu ý, ngay cả khi viết mã lệnh, bát phân dễ dàng hơn nhiều so với hex khi bạn đang làm việc trên (ví dụ) một kiến ​​trúc với từ 36 bit và ký tự 9 bit - 12 chữ số bát phân hiển thị chính xác một máy từ, với 3 chữ số cho mỗi ký tự. Nếu bạn đại diện cho cùng một từ 36 bit với 9 chữ số thập phân, bạn không thể dễ dàng biết giá trị của các ký tự riêng lẻ. –

+0

Như câu trả lời của tôi dưới đây giải thích, trình tự thoát ra \ uXXXX và bát phân bát phân được phân tích cú pháp ở các giai đoạn rất khác nhau. Chuỗi thoát \ uXXXX không phải là phiên bản mở rộng của chuỗi thoát bát phân của C. Chỉ cần đặt \ u000A vào một chuỗi và chương trình của bạn sẽ ngừng biên dịch. – Sven

1

Nếu tôi có thể hiểu được các quy tắc (hãy sửa lại cho tôi nếu tôi sai):

\ OctalDigit 
Examples: 
    \0, \1, \2, \3, \4, \5, \6, \7 

\ OctalDigit OctalDigit 
Examples: 
    \00, \07, \17, \27, \37, \47, \57, \67, \77 

\ ZeroToThree OctalDigit OctalDigit 
Examples: 
    \000, \177, \277, \367,\377 

\t, \n, \\ không thuộc quy tắc OctalEscape; chúng phải theo các quy tắc ký tự thoát riêng biệt.

Decimal 255 tương đương với bát phân 377 (sử dụng Windows Calculator trong chế độ khoa học để xác nhận)

Do đó một ba chữ số Octal giá trị rơi vào khoảng \000 (0) để \377 (255)

Do đó, \4715 không phải là giá trị bát phân hợp lệ vì nó có nhiều hơn ba chữ số bát phân. Nếu bạn muốn truy cập ký tự điểm mã với giá trị thập phân 4715, hãy sử dụng biểu tượng thoát Unicode \u để đại diện cho ký tự UTF-16 \u126B (4715 dưới dạng thập phân) vì mọi Java char đều bằng Unicode UTF-16.

từ http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Character.html:

The char data type (and therefore the value that a Character object encapsulates) are based on the original Unicode specification, which defined characters as fixed-width 16-bit entities. The Unicode standard has since been changed to allow for characters whose representation requires more than 16 bits. The range of legal code points is now U+0000 to U+10FFFF, known as Unicode scalar value. (Refer to the definition of the U+n notation in the Unicode standard.)

The set of characters from U+0000 to U+FFFF is sometimes referred to as the Basic Multilingual Plane (BMP). Characters whose code points are greater than U+FFFF are called supplementary characters. The Java 2 platform uses the UTF-16 representation in char arrays and in the String and StringBuffer classes. In this representation, supplementary characters are represented as a pair of char values, the first from the high-surrogates range, (\uD800-\uDBFF), the second from the low-surrogates range (\uDC00-\uDFFF).

được sửa đổi:

Bất cứ điều gì vượt quá giá trị bát phân có giá trị trong phạm vi 8-bit (lớn hơn một byte) là ngôn ngữ cụ thể. Một số ngôn ngữ lập trình có thể tiếp tục để phù hợp với việc thực thi Unicode; một số có thể không (giới hạn nó thành một byte). Java chắc chắn không cho phép nó mặc dù nó có hỗ trợ Unicode.

Một vài ngôn ngữ lập trình (nhà cung cấp phụ thuộc) mà giới hạn một byte literals bát phân:

  1. Java (tất cả các nhà cung cấp): - Một số nguyên liên tục bát phân bắt đầu với 0 hoặc một con số trong base-8 (lên đến 0377); \ 0 đến \ 7, \ 00 đến \ 77, \ 000 tới \ 377 (ở định dạng chuỗi nhị phân)
  2. C/C++ (Microsoft) - Hằng số nguyên bát phân bắt đầu bằng 0 (tối đa 0377); định dạng chuỗi bát phân dạng chữ \nnn
  3. Ruby - Hằng số nguyên bát phân bắt đầu bằng 0 (tối đa 0377); chuỗi bát phân định dạng đen \nnn

Một vài ngôn ngữ lập trình (nhà cung cấp phụ thuộc) có hỗ trợ chữ bát phân lớn hơn một byte:

  1. Perl - Một số nguyên liên tục bát phân bắt đầu với 0 ; bát phân chuỗi chữ dạng \nnn Xem http://search.cpan.org/~jesse/perl-5.12.1/pod/perlrebackslash.pod#Octal_escapes

Một vài ngôn ngữ lập trình không hỗ trợ chữ bát phân:

  1. C# - sử dụng Convert.ToInt32(integer, 8) cho cơ sở-8 How can we convert binary number into its octal number using c#?
+0

Có, tôi biết các giới hạn.Câu hỏi của tôi không phải là giới hạn, nhưng đúng hơn là _why_ những giới hạn đó ở đó, vì các ký tự Java không bị giới hạn trong phạm vi 0-255. Tôi sẽ làm rõ câu hỏi. – paxdiablo

+0

Tất nhiên, Java đang sử dụng Unicode 16 bit cho 'String' và' char'. Nhưng bây giờ, bạn đang sử dụng biểu tượng thoát '\' và bạn sử dụng nó để biểu thị giá trị bát phân chỉ cho phép lên đến '\ 377' ở định dạng thoát bát phân Java hoặc 255 trong giá trị thập phân. Định dạng thoát bát phân Java '\ 4715 'không phải là định dạng thoát bát phân hợp lệ vì nó có nhiều hơn ba chữ số theo các quy tắc OctalEscape trong JLS. – ecle

+0

Nếu bạn muốn truy cập hơn 255 điểm mã theo Unicode UTF-16 String/char, hãy sử dụng ký hiệu Unicode '\ u'. Vì vậy, đối với mã số điểm 4715 (?) Là '\ u4715' (dạng đúng, tôi nghĩ nó nên là' \ u126B' cho số thập phân 4715) – ecle

0

Các \ 0- \ 377 thoát bát phân cũng được thừa kế từ C, và những hạn chế làm cho một số tiền hợp lý của ý nghĩa trong một ngôn ngữ như C trong đó các ký tự == byte (ít nhất là trong các ngày halcyon trước khi wchar_t).

1

Câu trả lời thực sự cho câu hỏi "Tại sao" yêu cầu chúng tôi hỏi các nhà thiết kế ngôn ngữ Java. Chúng tôi không ở vị trí để làm điều đó, và tôi nghi ngờ rằng họ thậm chí sẽ ở trong một vị trí để trả lời. (Có thể bạn nhớ các cuộc thảo luận kỹ thuật chi tiết mà bạn đã có ~ 20 năm trước không?)

Tuy nhiên, một lời giải thích chính đáng cho điều này "hạn chế" là:

  • thoát bát phân được mượn từ C/C++, trong đó họ cũng bị hạn chế đến 8 bit,
  • bát phân là cũ lỗi thời và người dùng CNTT thường thích và thoải mái hơn với hệ thập lục phân và
  • Java hỗ trợ các cách thể hiện Unicode, bằng cách nhúng trực tiếp vào mã nguồn hoặc bằng cách sử dụng \u Thoát Unicode ... không giới hạn đối với chuỗi và ký tự chữ.

Thực ra, tôi chưa bao giờ nghe bất kỳ ai (ngoài bạn) cho rằng các số bát phân nên dài hơn 8 bit trong Java.


Ngẫu nhiên, khi tôi bắt đầu vào tính toán các bộ ký tự có khuynh hướng phần cứng cụ thể, và thường ít hơn 8 bit. Trong khóa học đại học của tôi, và công việc đầu tiên của tôi sau khi tốt nghiệp, tôi đã sử dụng các máy CDC 6000 có từ 60 bit và bộ ký tự 6 bit - "Mã hiển thị" Tôi nghĩ chúng tôi đã gọi nó. Octal hoạt động rất độc đáo trong ngữ cảnh này. Nhưng khi ngành công nghiệp hướng tới việc áp dụng phổ biến các cấu trúc bit 8/16/32/64, người ta ngày càng sử dụng hệ thập lục phân thay vì bát phân.

0

Tôi biết không có lý do tại sao thoát ra bát phân bị giới hạn ở các điểm mã hóa unicode 0 đến 255. Đây có thể là lý do lịch sử. Câu hỏi về cơ bản vẫn chưa được trả lời vì không có lý do kỹ thuật nào để không tăng phạm vi thoát vị bát phân trong quá trình thiết kế Java.

Tuy nhiên, cần lưu ý rằng có sự khác biệt không rõ ràng giữa lối thoát unicode và quãng tám thoát. Lối thoát bát phân chỉ được xử lý như là một phần của chuỗi trong khi thoát unicode có thể xảy ra ở bất kỳ đâu trong một tệp, ví dụ như một phần của tên của một lớp. Cũng lưu ý, rằng ví dụ sau thậm chí sẽ không biên dịch:

String a = "\u000A"; 

Lý do là, rằng \ u000A được mở rộng để một dòng mới ở giai đoạn rất sớm (về cơ bản khi tải tập tin). Các mã sau đây không tạo ra một lỗi:

String a = "\012"; 

các \ 012 được mở rộng sau trình biên dịch đã phân tích mã. Điều này cũng giữ cho các lần thoát khác như \ n, \ r, \ t, v.v.

Vì vậy, trong kết luận: thoát unicode KHÔNG thay thế cho thoát bát phân. Chúng là một khái niệm hoàn toàn khác. Cụ thể, để tránh bất kỳ vấn đề nào (như với \ u000A ở trên), người ta nên sử dụng lối thoát bát phân cho các điểm mã 0 đến 255 và thoát unicode cho các điểm mã trên 255.

Các vấn đề liên quan