| Kapitola/strana |
Poznámka |
| 3.3/34 |
Uvádíte, že:
Nesplňuje-li metoda main() zmíněné požadavky,
program nebude možné přeložit.
To není přesné, protože program samozřejmě přeložit jde.
Pouze není daná třída spustitelná a metoda main() se tak stává "obyčejnou"
statickou metodou.
Navrhovaná oprava:
Nesplňuje-li main() zmíněné požadavky, půjde
sice zdrojový soubor přeložit, ale nebude možné jej
spustit.
P.Herout
|
| 4.2/69 |
Inicializace třídy:
- Škoda, že není popsána také možnost, že lze pro inicializaci využít
nestatický inicializační blok.
Tato konstrukce je popsána v Java Language Specification, kapitola 8.6.
Následující příklad ukazuje jeho použití:
public class Initializer {
private Object field1 = new Object() {
{
System.out.println("Field 1 init");
}
};
{
/* Instance initializer */
System.out.println("Nestaticky inicializator");
}
private Object field2 = new Object() {
{
System.out.println("Field 2 init");
}
};
public Initializer() {
System.out.println(getClass() + ": prazdny konstruktor");
}
public Initializer(int param) {
System.out.println(getClass() + ": konstruktor s parametrem");
}
public static void main(String args[]) {
new Initializer();
new Initializer(1);
}
}
Výstupem programu bude:
Field 1 init
Nestaticky inicializator
Field 2 init
class Initializer: prazdny konstruktor
Field 1 init
Nestaticky inicializator
Field 2 init
class Initializer: konstruktor s parametrem
Z výstupu je dobře patrné pořadí jednotlivých kroků inicializace. Z programu je také vidět, že nestatický inicializační blok je jedinou možností, jak provést dodatečnou inicializaci v anonymních vnořených třídách.
Inicializačních bloků může být i více, pořadí jejich volání závisí na umístění ve zdrojovém kódu.
- Dle mého názoru by bylo vhodné uvést přesné pořadí operací v jakém konstrukce objektu probíhá.
To znamená:
- Konstruktor nadtřídy.
- Atributy třídy deklarované s inicializační výrazem + nestatické inicializační bloky.
- Konstruktor třídy.
- Chtěl bych upozornit na jedno úskalí při použití statických dat v třídě.
Jedná se o to, že za jistých okolností může být statická inicializace provedena vícekrát.
To je způsobeno tím, že při prvním odkazu na třídu je tato pomocí class loaderu
načtena do JVM, přičemž proběhne statická inicializace. Následně program může vytvářet instance
této třídy a pracovat s nimi. Problém nastává, jakmile není v programu odkaz na žádnou instanci
této třídy. Tím pádem se třída stává "adeptem pro odklizení" pomocí garbage collectoru.
Pokud je třída opravdu vyjmuta z JVM, tak při dalším odkazu na tuto třídu se třída načte a statická inicializace
se provede podruhé.
V mnoha případech toto chování nevadí, ale programátor by si měl uvědomit tuto zvlášnost Javy a
vyvarovat se provádění operací ve statických inicializátorech, které lze provést pouze jednou.
Jako řešení tohoto problému lze použít spustění JVM s parametrem -noclassgc -- potom
ale nejsou z paměti odstraňovány žádné nepoužívané třídy.
|
| 9.5/152 |
V knize je uveden kód podobný následujícímu:
int i = 123;
String s = String.valueOf(i);
System.out.println("i: " + s);
Tento způsob mi přijde zavádějící. Otázka zní proč nebylo využito standardního operátoru '+'
pro spojování řetězců. Kód může vypadat následovně:
int i = 123;
System.out.println("i: " + i);
Přitom přeložená třída je stejná jako předešlá, pouze je zápis mnohem přehlednější.
Podobný problém je vidět v poznámce pod čarou v 9.7/154 -- zde je nečitelnost kódu ještě
markantnější:
String s = "obr".concat(String.valueOf(i)).concat(".jpg")
místo
String s = "obr" + i + ".jpg"
Zarážející na tom je, že operátor '+' běžně používáte a doporučujete při volání metod
System.out.println(). Čtenář tak nabyde dojmu, že metoda
System.out.println() je "magická", ale přitom se jedná o obyčejnou
metodu, která je pouze přetížena pro všechny základní typy.
|
| 13.8/221 |
Zde píšete, že se u atributů rozhraní neuvádí explicitně jejich modifikátory. V
Java language specification se skutečně píše, že se by se tyto modifikátory
neměly uvádět (protože atributy rozhraní mají implicitní modifikátory
public static final a tyto nelze dále měnit).
Praxe je však úplně jiná. Pokud nahlédnete do zdrojových kódů Java Core API, tak
zjistíte, že se stalo nepsaným standardem tyto modifikátory uvádět jak u atributů,
tak u metod rozhraní.
|
| 14/224 |
Zde by bylo, dle mého názoru, zajímavé uvést poznámku pro programátory v C++, že
privátní, statické a final metody nevyužívají pozdní vazbu a vysvětlit důvody.
Jelikož metody s modifikátorem final není možné dále předefinovávat, nepotřebuje
JVM při jejich volání využívat pozdní vazby. Pro třídu a její potomky je díky této vlastnoti již v době překladu
známa metoda, která se má zavolat. To samé platí pro private metody, díky tomu, že každá private
metoda je automaticky také final.
|
| 20.6, 20.7 |
|