wtorek, 29 kwietnia 2008

Java Killers #003

Dzisiejsze Java Killers krótkie i proste z pozoru. Nie będziemy deklarować klas, tworzyć złożonych pętli, definiować rzadko używanych obiektów czy używać niespotykanych metod. Dziś po prostu dodamy do siebie dwie liczby: 221 i 7. Tak po prostu, zwykła suma i nic więcej. Czy może być coś prostszego? A więc jak zwykle, żeby nie przedłużać przejdźmy od razu do kodu:


1 package javakillers.part003;
2
3 /**
4 * @author pawel
5 */
6 public class Main {
7
8 public static void main(String[] args)
9 {
10 int val = (int) (22l + 7.0);
11 System.out.println("Value: " + val);
12 }
13 }
14
15

Proste prawda? No bo chyba prościej się nie da. No więc teraz najważniejsza sprawa. Co wypisze nam na ekran ten program? Odpowiedzi do wyboru macie cztery:

A) Value: 29
B) Value: 228
C) Program się nie skompiluje
D) Program rzuci wyjątek w czasie uruchomienia

Odpowiedź to oczywiście... A) Value: 29 No co, przecież to prosta matematyka 221 + 7 = 29! A tak poważnie problem tkwi w formatowaniu. Jeśli dobrze się przyjrzymy to zobaczymy, że nasza zmienna val obliczana jest na podstawie dwóch wartości: longa 22L oraz doubla 7.0. Tak właśnie, to było 22 a nie 221. Istota problemu jest taka, że wiele czcionek w bardzo podobny sposób renderuje nam literke l oraz cyfre 1. Kilka lat temu sławna była spora afera, gdzie ktoś zarejestrował domenę pay-pa1.com zamiast pay-pal.com i rozkradł ileś tam kont użytkowników PayPal'a. Ponieważ w javie definiując longa możemy explicite pokazać, że ten nasz long to rzeczywiście long (a nie żaden tam int czy inny) poprzez dodanie literki L na końcu, napotykamy jako programiści na ten sam problem, który swojego czasu wstrząsnął społecznością PayPal'a.

Prawda jest taka, że wszystko byłoby pięknie gdybym mógł pisać tylko tak:


long someVal = 22L;


Problem pojawia się, gdyż mogę tą zmienną zdefiniować również tak:


long someVal = 22l;


Duże czy małe "eL", dla Javy nie ma różnicy. Niby taka niewinna rzecz, ale problemów może przysporzyć... oczywiście do czasu uruchomienia debugera, kiedy wszystko staje się jasne :).

Jak się przed tym uchronić? Po prostu pisać L dużymi literami lub w IDE (czy notatniku) zmienić sobie czcionkę na jakąś porządną, na przykład taki Monospaced.


Dzisiejsze Java Killers nie było może jakimś specjalnym mykiem w języku, który zadziwił nas swoją funkcjonalnością, czy też specjalną, niszczącą funkcją zaszytą gdzieś w API. Dziś było inaczej, gdyż chodziło mi bardziej o pokazanie, że dokuczliwe błędy, mogą nas zaskoczyć w najmniej oczekiwanych sytuacjach, w miejscach kodu najbardziej dla nas wydałoby się oczywistych.

Pozostaje już tylko na zakończenie odpowiedzieć na dwa pytania: czy znaliście odpowiedź oraz czy cykl JK się Wam podoba? :)

8 komentarzy:

Anonimowy pisze...

Grrr... znowu źle ;-) Czytałem tego posta w czytniku RSS zintegrowanym z Operą, a tam literka l i cyfra 1 to już całkiem do nieodróżnienia były. Jak na razie mój wynik to 0:3 dla Ciebie. Czekam z niecierpliwością na kolejny post z cyklu Java Killers.

olektrolek pisze...

cykl jest ok, czekamy na wiecej

Anonimowy pisze...

tym razem nie dałem się nabrać :) W końcu zgadłem, ale wciąż jest 2:1 dla Ciebie. Fajny cykl, tak trzymaj!

Maciek pisze...

mnie to samo co u przedmówcy.. 2:1 ..
czekam na 2:2 ;p

Anonimowy pisze...

tym razem 1:0 dla mnie - ale to przez to ze raz piszesz 17 raz 7, przez co przyjrzalem sie dokladnie liczba :)

-- dr_bonzo

koziołek pisze...

Wygrałem. Zadanie fajne, ale słabo sprawdza się w necie, bo można użyć własnego stylu lub nie mieć okreslonej czcionki i wtedy klapa.

Paweł Szulc pisze...

@maciek & anonimowy: czekajcie czekajcie, kolejny nie bedzie taki mily ;)

@dr_bonzo: dzieki za info! nie zauwazylem 7 i 17, juz popawione :)

eximius pisze...

ten trick najlepiej pokazywac tak:
ile to jest: 12345+5432l
wtedy zlapiesz na to wiecej osob i nie bedziesz musial podawac w poscie "dodajmy teraz 221 i 7" bo to jest mylace.

pozdrawiam