Blíží se nám konec roku 2007 tak proč nepokračovat v mých představách změny jazyka, tj. takový malý výhled toho co by se v roce 2008 mohlo změnit.
V předchozím příspěvku jsem se rozjel na téma vylepšení programovaní paralelních programů. Dneska se pustím spíš do oblasti vylepšení psaní kódu, tj. změny, které cítím, že zpřehlední kód.
Vylepšení příkazu switch
Jistě všichni víme, že příkaz switch
funguje pouze nad typy int
a char
. Takže žádný long
, fload
, double
, natož např. String
(o tomto konkrétním typu hovořili pánové v JavaPosse #151). Kdo se podíval pod pokličku překladu switch
příkazu do bytecodu, zjistil, že k tomu slouží dvě instrukce, buď lookupswitch
nebo tableswitch
. V podstatě jde o to, že tato instrukce na základě hodnoty výrazu ve switch
příkazu skočí na správný case
. Pokud chceme vytvořit ekvivalent např. pro String
, pak použijeme kaskádu if - else if - else if ...
.Proč, ale nepovolit
switch
i pro jiné výsledné typy výrazu (např. String
) a až překladačem vše přeložit stejně jako onu kaskádu if
ů?Odchytávání více typů výjimek najednou při zachování typu výjimky
I v tomto případě jsem se nechal inspirovat povídáním pánů z JavaPosse. No představme si následující metodu:protected Object invokeMethod(String s) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException,
SecurityException, NoSuchMethodException
{
Method m = String.class.getMethod("toString", new Class[0] );
return m.invoke(s, new Object[0]);
}
Nyní chceme tuto metodu zavolat a vyhodit jinou výjimku v případě, že se nepodařilo najít metodu a jinou v případě, že se ji nepodařilo zavolat. Nemáme jinou volbu než:try {
invokeMethod("A");
} catch (IllegalArgumentException e) {
throw new CantInvokeException(e);
} catch (IllegalAccessException e) {
throw new CantInvokeException(e);
} catch (InvocationTargetException e) {
throw new CantInvokeException(e);
} catch (SecurityException e) {
throw new CantFindMethodException(e);
} catch (NoSuchMethodException e) {
throw new CantFindMethodException(e);
}
A to je vskutnu zvěrstvo. Nebylo by přeci jenom lepší něco následujícího:try {
invokeMethod("A");
} catch (IllegalArgumentException, IllegalAccessException,
InvocationTargetException: Exception e) {
throw new CantInvokeException(e);
} catch (SecurityException, NoSuchMethodException: Exception e) {
throw new CantFindMethodException(e);
}
Máme možnost specifikovat libovolný počet typů vyjímek, které chceme odchytit jediným catch
příkazem, za seznam přidáme dvojtečku a specifikujeme typ proměnné (v našem případě je nejbližším společným předkem výjimek typ Exception
, který je zároveň typem proměnné e
). Kloním se k variantě, že programátor musí specifikovat typ proměnné, nenechával bych to na překladači.Co znamená dodatek při zachování typu výjimky z názvu kapitoly? Pokud bychom kód z předchozího úryvku změnili na:
try {
invokeMethod("A");
} catch (IllegalArgumentException, IllegalAccessException,
InvocationTargetException: Exception e) {
//něco
throw e;
} catch (SecurityException, NoSuchMethodException: Exception e) {
//něco jiného
throw e;
}
a uvedli ho v metodě se stejnou klauzulí throws
jako má metoda invokeMethod
, pak bude vše v pořádku. Překladač se nebude zlobit, že se snažíme vyhodit výjimku typu Exception
z metody, která ji nemá uvedenou ve throws
, protože proměnná e
je typu Exception
, ale může nabývat pouze hodnot typů uvedených před dvojtečkou. Samozřejmě musí být final
(není tak uvedená, ale je).