it-swarm-tr.com

Java kodunu neden belirli Unicode karakterlerle yorumlarda yürütülüyor?

Aşağıdaki kod "Merhaba Dünya!" (hayır, gerçekten deneyin).

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

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

Bunun nedeni, Java derleyicisinin Unicode karakter \u000d karakterini yeni bir satır olarak ayrıştırması ve aşağıdakilere dönüştürülmesidir:

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

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

Böylece bir yorum "idam" olarak sonuçlandı.

Bu, kötü niyetli kodu "gizlemek" için kullanılabildiğinden veya kötü bir programcının aklına gelebilecek her neyse, neden yorumlara izin verilir ?

Buna neden Java spesifikasyonu tarafından izin verilmektedir?

1302
Reg

Unicode kod çözme, başka bir sözcük çevirisinden önce gerçekleşir. Bunun en önemli yararı, ASCII ile diğer kodlamalar arasında ileri geri gitmeyi önemsiz kılmasıdır. Yorumların nerede başladığını ve nerede biteceğini çözmene bile gerek yok!

JLS Bölüm 3.3 'de belirtildiği gibi, bu herhangi bir ASCII tabanlı aracın kaynak dosyaları işlemesini sağlar:

[...] Java programlama dili, Unicode ile yazılmış bir programı, bir programı ASCII tabanlı araçlar tarafından işlenebilecek bir forma dönüştüren ASCII biçimine dönüştürmenin standart bir yolunu belirtir. [...]

Bu, her zaman Java platformu için kilit bir amaç olan platform bağımsızlığı (desteklenen karakter setlerinin bağımsızlığı) için temel bir garanti verir.

Herhangi bir Unicode karakterini dosyanın herhangi bir yerine yazabilmek, latin olmayan dillerdeki kodları belgelerken zarif ve özellikle yorumlarda önemlidir. Anlambilimi bu kadar ince şekillerde engelleyebilmesi gerçeği, sadece (talihsiz) bir yan etkidir.

Bu konuda pek çok şey var ve Java Puzzlers Joshua Bloch ve Neal Gafter tarafından aşağıdaki değişken dahil edildi:

Bu yasal bir Java programı mı? Eğer öyleyse, ne yazdırır?

\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

(Bu program sade bir "Merhaba Dünya" programı olarak ortaya çıkıyor.)

Bilincin çözümünde, şunlara işaret ederler:

Daha ciddi olarak, bu yapboz önceki üçün derslerini güçlendirmeye hizmet ediyor: Unicode kaçışları, programınıza başka bir şekilde gösterilemeyen karakterleri girmeniz gerektiğinde çok önemlidir. Diğer tüm durumlarda onlardan kaçının.


Kaynak: Java: Yorumlarda kod çalıştırılıyor mu ?!

719
aioobe

Bu henüz ele alınmadığından, burada bir açıklama, Unicode çıkışlarının çevirisinin neden diğer kaynak kod işlemlerinden önce gerçekleştiğini açıklıyor:

Bunun arkasındaki fikir, farklı karakter kodlamaları arasında Java kaynak kodunun kayıpsız çevirilerine izin vermesiydi. Bugün, yaygın bir Unicode desteği var ve bu bir sorun gibi görünmüyor, ancak o zaman bir batı ülkesinden bir geliştiricinin Asya'daki meslektaşından Asya karakterleri içeren bazı kaynak kodları alması kolay değildi, derleme ve test etme dahil) ve sonucu bir şeyler zarar vermeden geri gönderme.

Böylece, Java kaynak kodu herhangi bir kodlamaya yazılabilir ve tanımlayıcılar, karakter ve Stringdeğişmezleri ve yorumları dahilinde çok çeşitli karakterlere izin verir. Daha sonra, kayıpsız bir şekilde aktarmak için, hedef kodlama tarafından desteklenmeyen tüm karakterler Unicode çıkışları ile değiştirilir.

Bu geri dönüşümlü bir işlemdir ve ilginç olan nokta, çevirinin kuralın bağlı olmadığından Java kaynak kodu sözdizimi hakkında hiçbir şey bilmesi gerekmeyen bir araçla çevirinin yapılabilmesidir. Bu, derleyici içindeki gerçek Unicode karakterlerine çeviri olarak, Java kaynak kodu sözdiziminde de bağımsız olarak gerçekleşir. Kaynak kodun anlamını değiştirmeden her iki yönde de istediğiniz sayıda çeviri adımını uygulayabileceğiniz anlamına gelir.

Bahsetmediğim bir başka tuhaf özelliğin sebebi de bu: \uuuuuuxxxx sözdizimi:

Bir çeviri aracı karakterlerden kaçıyorsa ve zaten çıkış dizisi olan bir diziyle karşılaştığında, diziye ek bir uekleyerek diziyi \ucafe'u \uucafe'a dönüştürmelidir. Anlamı değişmez, ancak diğer yöne dönüştürürken, araç yalnızca bir uöğesini kaldırmalı ve yalnızca Unicode karakterleriyle tek bir uiçeren dizileri değiştirmelidir. Bu şekilde, Unicode kaçarlar bile ileri geri dönüştürülürken orijinal hallerinde tutulur. Sanırım, hiç kimse bu özelliği kullanmamış…

136
Holger

Tamamen etkisiz bir şekilde nokta ekleyeceğim, sadece kendime yardım edemediğim ve henüz yapmadığını gördüğüm için, sorunun geçersiz olduğu, yani kodun içinde olduğu gizli bir öncül içerdiğinden sorunun geçersiz bir yorum!

Java kaynak kodunda\u000d, her şekilde bir ASCII CR karakterine eşdeğerdir. Nerede olursa olsun biten, sade ve basit bir çizgidir. Sorudaki biçimlendirme yanıltıcıdır, bu karakter dizisinin aslında sözdizimsel olarak karşılık geldiği şey şudur:

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

IMHO en doğru cevap bu nedenle: kod yürütür çünkü bir yorumda değildir; Bir sonraki satırda. "Yorumlarda kod çalıştırma", beklediğiniz gibi Java’ya izin verilmez.

Karışıklıkların çoğu, sözdizimi vurgulayıcılarının ve IDE'lerin bu durumu hesaba katacak kadar karmaşık olmamalarından kaynaklanmaktadır. Unicode kaçışlarını hiç işlemezler veya daha önce javac yaptığı gibi kodu ayrıştırdıktan sonra yaparlar.

100
Pepijn Schmitz

Bu, Java'nın orijinal tasarımına kadar giden kasıtlı bir tasarım seçimiydi.

"Kim Unicode'un yorumlarda kaçmasını istiyor?" Diye soranlara, ana dili Latince karakter kümesini kullanan kişiler olduklarını düşünüyorum. Başka bir deyişle, Java'nın orijinal tasarımında, kişilerin bir Java programında yasal olan yerlerde, en çok yorum ve dizelerde rasgele Unicode karakterleri kullanabileceği doğaldır.

Muhtemelen bu tür programların Unicode kaçışlarını yorumlayamadığı ve karşılık gelen glifi gösteremediği kaynak metni görüntülemek için kullanılan programlarda (IDE'ler gibi) bir eksikliktir.

21

@Zwol ile bunun bir tasarım hatası olduğu konusunda hemfikirim; ama ben daha da eleştiriyorum.

\u escape, string ve char değişmezlerinde yararlıdır; ve olması gereken tek yer orası. \n gibi diğer kaçışlarla aynı şekilde ele alınmalıdır; ve "\u000A" olmalıdır tam olarak "\n" anlamına gelir.

Yorumlarda \uxxxx sahibi olmanın hiçbir anlamı yoktur - kimse bunu okuyamaz.

Benzer şekilde, programın diğer bölümünde \uxxxx kullanmanın bir anlamı yoktur. Bunun tek istisnası, muhtemelen bazı ascii olmayan karakterleri içermeye zorlanan genel API’lerdedir - bunu en son ne zaman gördük?

Tasarımcıların 1995'te nedenleri vardı, ancak 20 yıl sonra bu yanlış bir seçim gibi görünüyor.

(okuyuculara soru - neden bu soru yeni oylar almaya devam ediyor? Bu soru popüler bir yerden bağlantıda mı?)

20
ZhongYu

Unicode'un kaçtığını neden uyguladıklarına cevap verebilen tek kişi, şartnameyi yazan kişilerdir.

Bunun makul bir nedeni, Java kaynak kodunun olası karakterleri olarak BMP değerine izin verme arzusunun olmasıdır. Bu olsa bir sorun sunar:

  • Herhangi bir BMP karakterini kullanabilmek istiyorsunuz.
  • Herhangi bir BMP karakteristiğini girmeniz oldukça kolay. Bunu yapmanın bir yolu Unicode kaçışlarıyla.
  • Sözcüksel özellikleri, insanların okuması ve yazması için kolay ve uygulanması da oldukça kolaydır.

Unicode kaçışları tehlikeye girdiğinde bu inanılmaz zor: bir sürü yeni sözlük kuralı yaratıyor.

Kolay yol, iki adımda lexing yapmaktır: ilk önce Unicode kaçışlarını temsil ettiği karakterle araştırın ve değiştirin, ardından elde edilen belgeyi Unicode kaçışlar yokmuş gibi ayrıştırın.

Bunun tersi, tanımlanması kolay olmasıdır, bu nedenle şartnameyi basitleştirir ve uygulaması kolaydır.

Dezavantajı, sizin örneğiniz.

11
Martijn