Java fejtörők – csapdák, buktató, és szélsőséges esetek. Ez egy könyv címe, amelynek szerzői J. Bloch és N. Gafter. Magyar nyelven a Kiskapu Kft. jelentette meg. A 2010-es magyar kiadás a 2005-ös angol nyelvű kiadás fordítása. A könyv weboldaláról (http://www.javapuzzlers.com), letölthető a 95 fejtörőhöz tartozó mintapéldák gyűjteménye, és elérhető a 270 oldalból minta fejezetként 28 oldalnyi tartalom 9 fejtörővel és azok részletes magyarázataival.
Messze nem mai az anyag, de teljesen örökzöld. Ma is kifejezetten igazán izgalmas átgondolni ezeket a fejtörőket. Biztos vagyok benne, hogy az igazán profiknak is nyújt újdonságot egy-egy fejtörő mögötti részletes magyarázat. Sokszor kiderül az a ravasz és csavaros magyarázatok között, hogy mire gondolt a költő, azaz mi volt/lehetett a Java programozási nyelv tervezése során a szakemberek elképzelése, illetve előfordultak-e kompromisszumok, amiknek persze következményei vannak.
A két részre bontott blog bejegyzés a könyv anyagából válogatva készült el. Ez az első rész, bevezető, alapozó szintű példákkal. A második rész haladó szintű példákat tartalmaz.
1. fejtörő: Mit ír ki program a konzolra?
1 2 3 4 5 6 |
public class Test { public static void main(String[] args) { System.out.println(12345+54321); System.out.println(12345+5432l); } } |
2. fejtörő: Mit ír ki program a konzolra?
1 2 3 4 5 6 7 8 9 10 |
public class Test { public static void main(String[] args) { String pig="length: 10"; String dog="length: "+pig.length(); System.out.println("Animals are equal: "+pig==dog); System.out.println(("Animals are equal: "+pig)==dog); System.out.println("Animals are equal: "+(pig==dog)); System.out.println("Animals are equal: "+pig.equals(dog)); } } |
3. fejtörő: Mit ír ki a program a konzolra?
1 2 3 4 5 6 7 8 9 10 11 |
/* * Generated by the IBM IDL-to-Java compiler, version 1.0 * from F:\TextRoot\apps\a1\units\include\PolicyHome.idl * Wednesday, June 17, 1998 6:44:40 o'clock AM GMT+00:00 */ public class Test { public static void main(String[] args) { System.out.print("Hell"); System.out.println("o World!"); } } |
4. fejtörő: Mit ír ki a program a konzolra?
1 2 3 4 5 6 7 |
public class Test { public static void main(String[] args) { System.out.print("browser:"); https://www.google.com; System.out.println(":maximize"); } } |
5. fejtörő: Mit ír ki a program a konzolra?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Test { private static boolean decision() { try { return true; } finally { return false; } } public static void main(String[] args) { System.out.println(decision()); } } |
6. fejtörő: Mit ír ki a program a konzolra?
1 2 3 4 5 6 7 |
public class Test { public static void main(String[] args) { String hello="Hello World!"; for(int i=0; i<hello.length(); i++) System.out.write(hello.charAt(i)); } } |
Részletes indoklások
További hasonló Java fejtörők, érdekességek
- Java 8 Puzzlers: 3 Java 8 Puzzles | Rebel
- Java Puzzlers – SlideShare
- Effective Java Puzzlers – moam.info
Tanfolyamainkon nem kifejezetten foglalkozunk hasonló problémákkal, de azért időnként feszegetjük a határokat. Természetesen részletesen indokoljuk, ha előkerül valamilyen hasonló eset. Általánosságban nem célunk, hogy extrém eseteken keresztül, a programozási nyelv gyenge pontjaira kihegyezve oktassuk a Java programozási nyelvet.
Ez volt az első rész, bevezető, alapozó szintű példákkal. Jöhet a második rész haladó szintű példákkal.
Én azt olvastam, hogy a törtek ábrázolása a C alapú nyelvekben elég pontatlan. Ki is próbáltam:
double
0.0-hoz hozzáadva 10-szer egymás után 0.1-et, ez jött ki:0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
Ugyanez
float
-tal:0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001
1.0000001
Róbert: így van. Mindig vigyázni kell a lebegőpontos adattípusokkal. Ha nagyon pontos számítás szükséges, vagy nem szeretnéd sok egymást követő művelet hibáját „összehalmozni”, akkor használj a primitív
float
vagydouble
típusok, vagy aFloat
vagyDouble
csomagolóosztályaik helyettjava.math.BigDecimal
osztályt.Megírtam Róbert 11-elemű
double
listáját kiíró programot hagyományosan:double x=0.0, d=0.1;
for(int i=1; i<=10; i++) {
System.out.println(x);
x+=d;
}
System.out.println(x);
Funkcionálisan hogyan lehetne megcsinálni ugyanezt?
Ha elegendő egy folyamba tenni a számokat és ezt kiírni a konzolra, akkor így (de persze több megoldás is van):
System.out.println(Stream.iterate(0.0, i->i+0.1).limit(11).
collect(Collectors.toList()));
Ekkor – röptében létrehozott adatszerkezettel – más műveleteket nem tudunk végrehajtani.
Ezt kapjuk eredményül:
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7, 0.7999999999999999, 0.8999999999999999, 0.9999999999999999]
Erre gondoltál Feri?
Igen, köszönöm. Tetszik ez a tömör forráskód. Kipróbáltam, hogy módosítva a generáló metódust a második listát is megkapom:
iterate(0.0f, i->i+0.1f)
.Úgy látom, már a generikusságot is érted. Ügyes vagy!
(Aki esetleg még nem van képben, errefelé keressen/kérdezzen, hogy összeálljon a kép ehhez a megoldáshoz:
Number
,Double
,Float
,Double.class
,Double.valueOf()
,doubleValue()
,Class<T>
,<T extends Number>
,n instanceof Float
és még: Generic, Autoboxing, Unboxing).