Java Source

Tuesday, September 02, 2008

Java books

A lot of people is asking me to recommend some books to read. Here is the list of those.

I have read these books about Java:
  • Ucebnice jazyka Java (CZE) - Pavel Herout
  • Thinking in Java (ENG) - Bruce Eckel
  • Java programujeme profesionalne (CZE) - Brett Spell
  • Java nastroje (CZE) - Martin Hynar
  • Java servlety a stranky JSP (CZE) - Marty Hall
  • Programujeme Jakarta Struts (CZE) - Chuck Caveness
  • Java 5 (CZE) - Rudolf Pecinovsky
  • SCJP 5 (ENG)
What was the best?
  1. SCJP 5 (ENG)
  2. Java 5 (CZE) - Rudolf Pecinovsky
  3. Thinking in Java (ENG) - Bruce Eckel
  4. Java programujeme profesionalne (CZE) - Brett Spell

I will add another info this week... That is all for today :~)

Wednesday, July 30, 2008

Something to read

http://www.eclipsezone.com/eps/10minute-rcp/
http://wiki.eclipse.org/index.php/Rich_Client_Platform
http://www.onjava.com/pub/a/onjava/2006/08/23/eclipse-rich-client-platform.html
http://www.vogella.de/articles/RichClientPlatform/article.html
http://ianskerrett.blogspot.com/2005/12/when-to-use-eclipse-rcp.html

Friday, February 15, 2008

WTF?

One friend of mine found and sent me the following code snippet :~)

return new Boolean("1".equals(session.getSetting(
SettingsConstants.DUMY)) ? true : false).booleanValue();


Unbelievably! To good to be true :~)

Sunday, January 06, 2008

Java 7

If you are interested in Java check the following link...
http://tech.puredanger.com/java7

Sunday, December 03, 2006

Kolekce v jazyku Java

Kolekce v programovacím jazyku Java slouží k ukládání, procházení (výběr) a mazání prvků. Java poskytuje několik typů kolekcí pro tuto funkčnost. Všechny však mají něco společného, mají společné rozhraní java.util.Collection (snad až na Map, TreeMap, SortedMap a příbuzné). Collection definuje základní metody pro práci nad kolekcemi.

Collection je základní rozhraní, od kterého dědí všechny ostatní rozhraní pro kolekce. Jaké třídy implementují rozhraní Collection můžeme nalézt v Java API (http://java.sun.com/j2se/1.5.0/docs/api/).

Když porovnáte kolekce v Java 5 s kolekcemi v Java 1.4, tak zásadní změna je v obohacení o parametrizované typy. Dále přibyly další kolekce.

Ve starších verzích Javy (verze 1.1) byla dostupná pouze kolekce Vector. Vector se dal procházet buď indexově (jako pole) nebo pomocí Enumeration. V několika knihách jsem se dočetl, že Vector je zastaralý a neměl by se používat. Měl by se, podle nich, na místo Vector použít ArrayList. Abych Vector neoprávněně neodsuzoval, udělal jsem si malý výkonnostní test a vyšlo mi, že Vector je pomalejší od ArrayList o nějakých cca 10%. Není to ovšem vina špatných algoritmů, nebo špatné implementace. Je to proto, že Vector je serializovaný a ArrayList nikoli. Proto Vector není nijak zastaralý a odsouzený k zániku. Je nevýkonný tehdy, když ho použijete na špatném místě. Jak to bývá ostatně kdykoli, když se používají nesprávné postupy, když člověk neví co přesně a proč dělá. Kdyby ho autoři jazyka nechtěli, tak by ho snad daly alespoň deprecated.
Proto řeči "Já mám raději ArrayList, protože je novější, Vector je zastaralý a pomalý!" jsou neopodstatněné.

Od verze 1.2 byly do Javy přidány další kolekce a byla rozšířena jejich funkčnost.

Základní rozdělení v rozhraní (s příslušnými podtřídami):
1. Collection
1.1 List (ArrayList, Vector, Stack)
1.2 Set (HashSet, LinkedHashSet)
1.2.1 SortedMap (TreeSet)
1.3 Queue (LinkedList)
2 Map (SortedMap, HashMap, LinkedHashMap, Hashtable, WeakHashMap)
2.1 SortedMap (TreeMap)

Seznam není úlpný a ani není třeba ho ani doplňovat. Například v seznamu chybí kolekce pro Enum, ale o těch bych se chtěl rozepsat někdy jindy a podrobněji. Pro to, jaké kolekce nám Java poskytuje se stačí podívat do API.

Nyní si popíšeme a ukážeme vhodné použití kolekcí. Při popisu nebudu vypisovat všechny metody, které kolekce poskytují. Budu se více zaměřovat na funkcionalitu, vhodné použití a optimalizaci.

1. ArrayList
ArrayList je jedna ze základních kolekcí. Je to třída, která implementuje rozhraní List. Jednoduše se dá říct, že je to dynamické (nafukovací) pole. O bufferování ArrayListu se můžeme prosadit sami, nebo to nechat na automatické správě bufferu ArrayListu.
Pokud chceme a víme, že budeme potřebovat vložit do ArrayList 10 000 prvků hned při vložení, ArrayList patřičně inicializujeme: new ArrayList(10000). Pokud nevíme kolik prvků bude vloženo do kolekce (a víme, že jich moc nebude) inicializujeme třídu ArrayList výchozím postupem: new ArrayList().

Příklad: Při vytvoření ArrayList se inicializuje pole o velikosti například 1 000. Až vyplníme kolekci (pole), vytvoří se jiné větší pole, do kterého se překopíruje obsah předchozího pole. A můžeme pokračovat v plnění. Jde vidět, že se ArrayList chová jako StringBuffer.

Pokud bychom chtěli aplikaci optimalizovat a vyladit práci s kolekcemi, můžeme si napsat malý statistický program. Ten by nám zjišťoval jaká je počáteční velikost, velikost po naplnění a velikost po některém dalším přidání prvků. Z toho bychom viděli a měli přesný přehled s jakou hodnotou inicializovat ArrayList.

Další věc, kterou bychom měli dodržovat a každé rozumné IDE to vyžaduje, je vytvářet typově bezpečné kolekce. Když nebyly generické typy (parametrizované typy, šablony, ...) vytvářely se třídy, které zaobalily kolekcí a nedovolily nikomu vložit do kolekce dva nebo více různých typů.
Zjednodušeně něco jako toto:

class StringArrayList {
private List list = new ArrayList();
public void add(String s) {
list.add(s);
}
public String get(int i) {
return (String) list.get(i);
}
}

S použitím generických typů se všechno zjednodušuje a odpadá nutnost implementovat tuto třídu. Typově bezpečnou kolekci vytvoříme takto:
List <String> list = new ArrayList <String>()
.
O tom co to znamená jsem už něco napsal, tak se na to teď odkazuji.

2. Vector
Vector má stejně jako ArrayList stejné předky. Liší se od ArrayListu tím, že je synchronizovaný.

3. Stack
4. HashSet
5. LinkedHashSet
6. TreeSet
7. LinkedList
8. SortedMap
9. HashMap
10. LinkedHashMap
11. Hashtable
12. WeakHashMap
13. TreeMap

Friday, December 01, 2006

Generické DAO

Nač použít generické typy? Tak například pro vytvoření generického DAO návrhového vzoru.
Když napíšeme DAO pomocí generických typů, můžeme pak ukládat jakékoli třídy. Samozřejmě že předním musíme nějak pro databázi namapovat. To by ovšem mělo být v moci daného DAO.

Nejdříve vytvoříme interface, a nadefinujeme jak naše DAO objekty budou vypadat. Dále přidáme generické typym kde "T" bude představovat ukládaný objekt, a "N" bude id (klíč) k danému objektu.
public interface GenericDao <T, N extends Serializable> {
N create(T o);
T read(N id);
void update(T o);
void delete(T o);
}


Po té co je interface hotov tak můžeme začít s jeho implementací. Následující implementace bude pro Hibernate. Samozřejmě že to můžeme naimplentovat jak chceme, a tady je jeden ze způsobů.
public class GenericDaoHibernate <T, N extends Serializable> implements GenericDao <T, N> {

private Class type;

public GenericDaoHibernateImpl(Class type) {
this.type = type;
}
public N create(T o) {
return (N) HibernateUtil.getSession.save(o);
}
public T load(N id) {
return (T) HibernateUtil.getSession.load(type, id);
}
public void update(T o) {
HibernateUtil.getSession.update(o);
}
public void delete(T o) {
HibernateUtil.getSession.delete(o);
}
}


Jde vidět, že používáme třídu HibernateUtil, ta slouží pro poskytování přístupu do databáze. Ve skutečnosti jen poskytuje Session, která nám umožňuje pracovat s databází.

Jak jde vidět generické typy při vhodném použití poskytují mocný nástroj pro vývoj.

Generické typy

Když jsem si stáhnul a nainstaloval Java 5 na svůj počítač, byl jsem zvědavý jaké nové funkčnosti nám tato nová verze přinese. Okamžitě jsem si koupil knížku od Rudolfa Pecinovského, "Java 5.0 - Novinky jazyka a upgrade aplikací" a pustil jsem se do objevování co nového je.

Zajimavé jsou všechny nové funkčnosti. Až snad na enum, ty nepracují tak jak mají a když se snažíte o serializaci, tak se Vám nepodaří nalézt nastavené hodnoty. Zkrátka enum v Jave pořádně nefungují. Proto budeme muset jestě nějakou dobu používat vlastnoruční enumy.

O čem jsou generycké typy? Jednodušše řečeno, generické typy slouží pro vytváření abstraktních znovu použitelných typů. Tím se stává třída velmi mocná. Využít toho lze pro vytváření znovu použitelných tříd (například lze vytvořít "Generické DAO") . Dálší z hlavních funkčností je vytvoření typově bezpečných kolekcí.

Jak lze využít generických typů pro zajištění typově bezpečných kolekcí můžeme vidět v následujícím kódu.

Tato konstrukce nám zajistí typovou bezpečnost kolekce, to znamená, že pokud se pokusíme přidat do těchto kolekcí něco jiného něz jsme nadefinovaly, nepodaří se nám to ani zkompilovat natož spustit. Následující výpis kódu ukazuje jak toto vhodně použít.
List<String> stringList = new ArrayList<String>();
stringList.add("retezec");


Zde je ukázka pokusu vložit objekt jiného typu do typově bezpečné kolekce. Tato snaha skončí neuspěšným pokusem o přeložení.
stringList.add(new Integer(0));

Co se děje na pozadí při vložení objektu správného typu? Překladač, jednoduše řečeno, udělá následné.
List stringList = new ArrayList();
stringList.add("retezec");

Nebo by se dalo říct, že jen ořeže kolekci od generických typů. A proč? Hlavní je zajistit, aby programor nevědomky (nebo snad ne umyslně) neplnil kolekci jiným typem. Doposud to šlo řešit tak že se vytvořila třída, která zaobalila kolekci svými metodami a zajistila tak typovou bezpečnost, zatím co kolekce byla pro okolí neviditelná.

Pro to, co lze nyní napsat jedním řádkem se musela napsat celá třída. Zjednodušeně by se dalo říct, že jde v tomto případě jen pro programátorovo pohodlí.

Wednesday, November 29, 2006

Java - String a metoda intern()

Jelikož se na různých místech v aplikaci vyskytují co do obsahu stejné řetězce, tak aby nedocházelo k plýtvání pamětí a ke ztrátám na výkonu režijemi, udržuje si Java tyto řetězce ve speciálním pool. Stejné řetězce jsou po nějaké "chvíli" po vytvoření, jestli ne hned, uloženy do tohoto pool. Když si tedy zažádáme (např.: vytváříme String s = "HelloWorld") o nějaký takový řetězec, je nám vrácen ten, který byl do poolu uložen.
Příklad:
String helloWorld = "HelloWorld";
helloWorld = helloWorld.intern();

intern() - Tato metoda souvisí s tím, že String se v aplikacích docela často používá a má proto trochu speciální zacházení ze strany překladače i JVM. Z důvodu výkonostního.

Metoda intern() dělá to, že uloží řetězec do tohoto poolu, nebo pokud už tam jiný String se stejným obsahem je, vrátí ten String z poolu. Ten speciální případ, kdy s používá pool je, když vytvoříte nový String pomocí literálu v Javě, tedy např.
String helloWorld = "HelloWorld";

Metoda intern() tedy slouží k uložení do poolu pro případ, že String vznikl nějak jinak. Celé to má význam pro ušetření paměti a urychlení porovnání Stringů (metodou equals()). Když vytvoříte dva Stringy se stejným obsahem
String helloWorld = "HelloWorld";
a String helloWorld2 = "HelloWorld";
bude to ve skutečnosti jeden objekt a ušetří se paměť. Při porovnání na equals(), se nejprve porovná identita (==) a teprve pokud nesouhlasí, porovnává se znak po znaku. Z toho plyne, že pokud jde o dva stejné objekty, porovnání na identitu je rychlejší.

Na druhé straně, využití metody inter() není tak akutní jak se zdá. Jednak vyvolání String.intern() nějakou dobu trvá a jednak není dost jasné jak se algoritmus pro ulkádání řetězců zachová.

Nabízejí se tedy dvě možnosti:
1. První je zavolat na String intern() a zaručit že String zůstane v poolu navěky. Tímto postupem by mohla dojít paměť...
2. Za druhé String, na který bylo zavoláno intern() zůstáva v pool do té doby, dokud je na něj reference. Tím je volání metody intern() více méně zbytečné a volání této metody vás jen brzdí.

Využívat intern() je tedy vhodné jen tehdy, když víte že daný řetězec v paměti potřebujete a chcete vědět, že ho tam i máte.

A kdo tedy pochopil o co jde, bude schopen správně udělat následující test. Co vypíše následující kód?

String hello1 = "hello";

String hello2 = new String("hello");

System.out.println(hello1 == hello2);

System.out.println(hello1 == (String)hello2);

System.out.println(hello1 == hello2.toString());

System.out.println(hello1 == hello2.toString().intern());

System.out.println(new String(hello1) == hello2);

System.out.println(hello1 == hello2.intern());

System.out.println(new String(hello1) == hello2.intern());

System.out.println(new String(hello1).intern() == hello2.intern());

Hibernate - vytvoření a update databáze

To jestli chceme databázi při každém spuštění aplikace vytvářet nebo ponechat, lze nastavit v konfiguračním souboru *.cfg.

Toto je vhodná volba pro testování při vytváření aplikace. Někdy však můžeme ocenit možnost vytvořit nebo aktualizovat databazi bez zásahu do konfiguračního souboru. K tomu použijeme třídy org.hibernate.cfg.Configuration, org.hibernate.tool.hbm2ddl.SchemaUpdate a org.hibernate.tool.hbm2ddl.SchemaExport.

Pro vytvoření databáze můžeme napsat následující kód:

Configuration c = newConfiguration().configure

("ormmapping/hibernate.cfg.xml");
SchemaExport se = new SchemaExport(c);
se.execute(true, true, false, false);

Pro update databáze napíšeme:

Configuration c = newConfiguration().configure
("ormmapping/hibernate.cfg.xml");
SchemaUpdate su = new SchemaUpdate(c);
su.execute(true, true);