SORU
29 Ocak 2011, CUMARTESİ


Neden Java tanımlayıcıları kontrol karakterlere izin veriyor mu?

Gizem

Java tanımlayıcıları izin verildi tam olarak keşfetmek, bir hata olması neredeyse kesin gibi son derece ilginç bir şey tökezledi.

İsterdim beklendiği üzere Java tanımlayıcıları uyduğu için ihtiyacı olan başlıyorlar karakter olan Unicode özelliği ID_Start ve ardından o özelliği ID_Continue ile bir özel durum için verilen önde gelen bir alt çizgi ve dolar işareti. Durum böyle olmamış. ne gördüm, ne de işittiğim ya da normal bir tanımlayıcı başka fikri olan aşırı sapma.

Kısa Demo

Aşağıdaki gösteri ASCII ESC karakteri (sekizli 033) Java tanımlayıcıları: izin olduğunu kanıtlayan düşünün

$ perl -le 'print qq(public class escape { public static void main(String argv[]) { String var_\033 = "i am escape: \033"; System.out.println(var_\033); }})' > escape.java
$ javac escape.java
$ java escape | cat -v
i am escape: ^[

O daha da kötü aslında. Çok daha kötü, hatta neredeyse. Hatta boş Değerlere izin verin! Ve diğer kodlar binlerce hatta tanımlayıcı bir karakter değildir işaret eder. Solaris, Linux ve Mac Darwin çalışan bu test ettik, ve hepsi aynı sonucu verir.

Uzun Bir Demo

Burada oldukça outrageuosly Java tüm bu beklenmeyen kod noktaları gösteren bir test programı sağlar yasal bir tanımlayıcı adının bir parçası olarak.

#!/usr/bin/env perl
# 
# test-java-idchars - find which bogus code points Java allows in its identifiers
# 
#   usage: test-java-idchars [low high]
#   e.g.:  test-java-idchars 0 255
#
# Without arguments, tests Unicode code points
# from 0 .. 0x1000.  You may go further with a
# higher explicit argument.
#
# Produces a report at the end.
#
# You can ^C it prematurely to end the program then
# and get a report of its progress up to that point.
#
# Tom Christiansen
# tchrist@perl.com
# Sat Jan 29 10:41:09 MST 2011

use strict;
use warnings;

use encoding "Latin1";
use open IO => ":utf8";

use charnames ();

$| = 1;

my @legal;

my ($start, $stop) = (0, 0x1000);

if (@ARGV != 0) {
    if (@ARGV == 1) {
        for (($stop) = @ARGV) { 
            $_ = oct if /^0/;   # support 0OCTAL, 0xHEX, 0bBINARY
        }
    }
    elsif (@ARGV == 2) {
        for (($start, $stop) = @ARGV) { 
            $_ = oct if /^0/;
        }
    } 
    else {
        die "usage: $0 [ [start] stop ]\n";
    } 
} 

for my $cp ( $start .. $stop ) {
    my $char = chr($cp);

    next if $char =~ /[\s\w]/;

    my $type = "?";
    for ($char) {
        $type = "Letter"      if /\pL/;
        $type = "Mark"        if /\pM/;
        $type = "Number"      if /\pN/;
        $type = "Punctuation" if /\pP/;
        $type = "Symbol"      if /\pS/;
        $type = "Separator"   if /\pZ/;
        $type = "Control"     if /\pC/;
    } 
    my $name = $cp ? (charnames::viacode($cp) || "<missing>") : "NULL";
    next if $name eq "<missing>" && $cp > 0xFF;
    my $msg = sprintf("U X %s", $cp, $name);
    print "testing \\p{$type} $msg...";
    open(TESTPROGRAM, ">:utf8", "testchar.java") || die $!;

print TESTPROGRAM <<"End_of_Java_Program";

public class testchar { 
    public static void main(String argv[]) { 
        String var_$char = "variable name ends in $msg";
        System.out.println(var_$char); 
    }
}

End_of_Java_Program

    close(TESTPROGRAM) || die $!;

    system q{
        ( javac -encoding UTF-8 testchar.java \
            && \
          java -Dfile.encoding=UTF-8 testchar | grep variable \
        ) >/dev/null 2>&1
    };

    push @legal, sprintf("U X", $cp) if $? == 0;

    if ($? && $? < 128) {
        print "<interrupted>\n";
        exit;  # from a ^C
    } 

    printf "is %s in Java identifiers.\n",  
        ($? == 0) ? uc "legal" : "forbidden";

} 

END { 
    print "Legal but evil code points: @legal\n";
}

Burada ne boşluk ne de tanımlayıcı karakter olan sadece ilk 33 kod noktaları bu program çalışan bir örnek:

$ perl test-java-idchars 0 0x20
testing \p{Control} U 0000 NULL...is LEGAL in Java identifiers.
testing \p{Control} U 0001 START OF HEADING...is LEGAL in Java identifiers.
testing \p{Control} U 0002 START OF TEXT...is LEGAL in Java identifiers.
testing \p{Control} U 0003 END OF TEXT...is LEGAL in Java identifiers.
testing \p{Control} U 0004 END OF TRANSMISSION...is LEGAL in Java identifiers.
testing \p{Control} U 0005 ENQUIRY...is LEGAL in Java identifiers.
testing \p{Control} U 0006 ACKNOWLEDGE...is LEGAL in Java identifiers.
testing \p{Control} U 0007 BELL...is LEGAL in Java identifiers.
testing \p{Control} U 0008 BACKSPACE...is LEGAL in Java identifiers.
testing \p{Control} U 000B LINE TABULATION...is forbidden in Java identifiers.
testing \p{Control} U 000E SHIFT OUT...is LEGAL in Java identifiers.
testing \p{Control} U 000F SHIFT IN...is LEGAL in Java identifiers.
testing \p{Control} U 0010 DATA LINK ESCAPE...is LEGAL in Java identifiers.
testing \p{Control} U 0011 DEVICE CONTROL ONE...is LEGAL in Java identifiers.
testing \p{Control} U 0012 DEVICE CONTROL TWO...is LEGAL in Java identifiers.
testing \p{Control} U 0013 DEVICE CONTROL THREE...is LEGAL in Java identifiers.
testing \p{Control} U 0014 DEVICE CONTROL FOUR...is LEGAL in Java identifiers.
testing \p{Control} U 0015 NEGATIVE ACKNOWLEDGE...is LEGAL in Java identifiers.
testing \p{Control} U 0016 SYNCHRONOUS IDLE...is LEGAL in Java identifiers.
testing \p{Control} U 0017 END OF TRANSMISSION BLOCK...is LEGAL in Java identifiers.
testing \p{Control} U 0018 CANCEL...is LEGAL in Java identifiers.
testing \p{Control} U 0019 END OF MEDIUM...is LEGAL in Java identifiers.
testing \p{Control} U 001A SUBSTITUTE...is LEGAL in Java identifiers.
testing \p{Control} U 001B ESCAPE...is LEGAL in Java identifiers.
testing \p{Control} U 001C INFORMATION SEPARATOR FOUR...is forbidden in Java identifiers.
testing \p{Control} U 001D INFORMATION SEPARATOR THREE...is forbidden in Java identifiers.
testing \p{Control} U 001E INFORMATION SEPARATOR TWO...is forbidden in Java identifiers.
testing \p{Control} U 001F INFORMATION SEPARATOR ONE...is forbidden in Java identifiers.
Legal but evil code points: U 0000 U 0001 U 0002 U 0003 U 0004 U 0005 U 0006 U 0007 U 0008 U 000E U 000F U 0010 U 0011 U 0012 U 0013 U 0014 U 0015 U 0016 U 0017 U 0018 U 0019 U 001A U 001B

Ve burada başka bir gösteri

$ perl test-java-idchars 0x600 0x700 | grep -i legal
testing \p{Control} U 0600 ARABIC NUMBER SIGN...is LEGAL in Java identifiers.
testing \p{Control} U 0601 ARABIC SIGN SANAH...is LEGAL in Java identifiers.
testing \p{Control} U 0602 ARABIC FOOTNOTE MARKER...is LEGAL in Java identifiers.
testing \p{Control} U 0603 ARABIC SIGN SAFHA...is LEGAL in Java identifiers.
testing \p{Control} U 06DD ARABIC END OF AYAH...is LEGAL in Java identifiers.
Legal but evil code points: U 0600 U 0601 U 0602 U 0603 U 06DD

Soru

Herkes görünüşte deli bu davranışını açıklayabilecek olan var mı? Orada birçok, birçok, açıklanamaz izin diğer birçok kod her yerde, U ile belki de en garibi, hangi 0000, hemen Başlangıç noktaları. İlk 0x1000 kod noktaları üzerinde çalıştırmak, belirli bir desen görünür özelliği Current_Symbol ile herhangi bir kod noktaları izin gibi görüyorsunuz. Ama onu çok fazla şey tamamen anlaşılmaz, en azından bana göre.

CEVAP
29 Ocak 2011, CUMARTESİ


Character.isJavaIdentifierStart() Character.isJavaIdentifierPart() Java Language Specification section 3.8 kadar erteledi. İkincisi, diğer koşullar arasında boşluk olmayan denetim karakterleri (bütün C1 aralığı, bakın liste için bağlantı da dahil olmak üzere) sağlar Character.isIdentifierIgnorable().

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Distractify

    Distractify

    1 Aralık 2011
  • ibebrent

    ibebrent

    23 Temmuz 2007
  • Mr. H

    Mr. H

    1 Temmuz 2012