Jazyk Java
Java je programovací jazyk, který byl zpočátku navržen jako přenositelný, objektově orientovaný, robustní, výkonný, interpretovaný a dynamický. V Javě lze jednoduše implementovat i paralelní výpočty pomocí vláken a monitorů. Vývoj Javy zahájil v roce 1991 James Gosling a původně byl jazyk určen pro set-top boxy.
Syntakticky je Java podobná jazyku C++, ale v mnoha rysech je mnohem jednodušší. Právě jednoduchost Javy možná stojí za její rostoucí oblibou ve školství. Člověku se dostane pod kůži syntaxe, kterou může později využít v C++ a zároveň se naučí pracovat s objekty, neboť bez jejich znalosti se v dnešní době nelze obejít.
Základní rysy jazyka
Java je jazyk interpretovaný – to znamená, že jsou programy předloženy virtuálnímu stroji – JVM (Java Virtual Machine) – který se postará o jejich konkrétní provedení na dané platformě. Program v Javě lze tedy spustit na jakémkoliv zařízení, pro které existuje implementace virtuálního stroje. Pro nejrozšířenější platformy, jako je Windows, Linux, Solaris a MacOS, jsou tyto virtuální stroje samozřejmostí.
Zdrojový kód každé třídy se nachází v souboru s příponou .java. Tyto soubory se nejprve zkompilují do tzv. bytekódu (instrukce pro virtuální zásobníkově orientovaný procesor), který je zapsán do stejnojmenných souborů s příponou .class. Tyto souboru v bytekódu už lze spustit pomocí JVM. Obvykle se však zkompilované soubory spolu s dalšími „zabalí“ do balíčku s příponou .jar a až tento balík se distribuuje mezi konečné uživatele.
Každá aplikace vytvořená v Javě se skládá z jedné nebo více tříd, které jsou organizovány v balíčcích (příslušnost třídy k danému balíčku se definuje příkazem package NÁZEV na začátku zdrojového kódu třídy).
Program v Javě tedy obsahuje:
- Třídy (class) = schéma (plán) pro vytváření objektů (instancí této třídy)
- Balíčky (package) = adresář (modul) s třídami, které patří logicky k sobě
Jedna ze tříd (tzv. hlavní třída) musí obsahovat metodu main() s následující hlavičkou:
zdrojový kód (Java) - zobrazit (66 znaků)
Tuto speciální metodu zavolá virtuální stroj (JVM) v okamžiku spuštění vaší aplikace.
Každá třída by se měla nacházet ve stejnojmenném souboru. Třída Pes by se tedy měla nacházet v souboru Pes.java. Kromě názvu třídy existuje ještě tzv. kvalifikovaný název, který kromě názvu třídy obsahuje i její přesné umístění v balíčcích (jednotlivé vnořené balíčky se oddělují tečkou).
Příklady kvalifikovaných názvů:
- třída Pes = zvirata.savci.Pes
- třída Editor = formulare.Editor
- třída JButton = javax.swing.JButton
- třída List = java.util.List
Chceme-li ve zdrojovém kódu použít třídu, která se nachází v jiném balíčku, musíme to kompilátoru sdělit pomocí příkazu import KVALIFIKOVANÝ NÁZEV.
Datové typy
Primitivní datové typy
I když je Java plně objektově orientovaná, přesto z výkonnostních důvodů obsahuje primitivní datové typy, které nejsou samy o sobě objekty.
| Datový typ | Typ | Velikost | Kódování |
|---|---|---|---|
| byte | celočíselný | 8 bitů | dvojkový doplněk, se znaménkem |
| short | celočíselný | 16 bitů | dvojkový doplněk, se znaménkem |
| int | celočíselný | 32 bitů | dvojkový doplněk, se znaménkem |
| long | celočíselný | 64 bitů | dvojkový doplněk, se znaménkem |
| float | reálný | 32 bitů | IEEE 754 |
| double | reálný | 64 bitů | IEEE 754 |
| boolean | logický | N/A, počítá se jako 1 bit | N/A |
| char | znakový | 16 bitů | N/A |
Objekty
Jazyk Java je založen na objektech a vše (kromě primitivních datových typů) je objekt. Všechny třídy, které nemají uvedeného předka, jsou potomky univerzální třídy Object a dědí od ní několik užitečných metod, například pro převod na řetězec (toString()), zjištění identity (equals(), hashcode()) a metody pro synchronizaci vláken (wait(), notify(), notifyAll()). Existuje i speciální hodnota null, která je také „potomkem“ třídy Object a znamená „nic“ nebo „nedefinováno“.
Obalové třídy
Pro práci s primitivními datovými lze pro každý primitivní datový použít tzv. obalovou třídu. I tyto obalové třídy jsou potomky třídy Object. Java nabízí tyto obalové třídy: Byte, Short, Integer, Long, Float, Double, Boolean, Character.
Vlastní třídy
Základem programování v Javě je vytváření vlastních tříd. Každá třída obsahuje atributy (třídní proměnné) a metody (třídní funkce).
Dále mají třídy tzv. konstruktor, což je speciální metoda se stejným názvem jako třída (bez návratového typu), kterou virtuální stroj (JVM) zavolá při vytváření nové instance dané třídy. Konstruktor má za úkol především incializovat počáteční stav objektu, např. inicializovat proměnné.
Pro přístup k proměnným a metodám dané instance třídy se používá speciální klíčové slovo this. Tento konstrukt v sobě nese referenci na aktuální instanci třídy (tedy tu, se kterou procesor právě pracuje).
Následuje jednoduchý příklad vlastní třídy.
public class Dog
{
private String name;
private String status;
public Dog (String name)
{
this.name = name;
this.status = "čeká";
}
public void goEat ()
{
this.status = "jí";
}
public void goPlay ()
{
this.status = "si hraje";
}
@Override
public String toString ()
{
return "Tvůj pejsek '" + this.name + "' " + this.status + ".";
}
public static void main (String[] args)
{
Dog myDog = new Dog ("Astra");
System.out.println (myDog.toString ());
myDog.goEat ();
System.out.println (myDog.toString ());
myDog.goPlay ();
System.out.println (myDog.toString ());
}
}
zdrojový kód (Java) - zobrazit (664 znaků)
Další příklad ukazuje použití pole a generování náhodných čísel.
public class Cube
{
private int counts[];
public Cube ()
{
this.counts = new int[6];
this.reset ();
}
private void reset ()
{
for (int i = 0; i < this.counts.length; i ++)
{
this.counts[i] = 0;
}
}
public void throwCube ()
{
int number = this.getRandomNumber (1, 6);
this.counts[number - 1] ++;
}
public void printStats ()
{
for (int i = 1; i <= this.counts.length; i ++)
{
System.out.println ("Počet hodů čísla " + i + ": " + this.counts[i - 1]);
}
}
private int getRandomNumber (int min, int max)
{
return min + (int) (Math.random () * (double) max);
}
public static void main (String[] args)
{
Cube myCube = new Cube ();
for (int i = 0; i < 1000; i ++)
{
myCube.throwCube ();
}
myCube.printStats ();
}
}
zdrojový kód (Java) - zobrazit (852 znaků)
Modifikátory přístupu
Přístup k proměnným, metodám je možné omezit pomocí tzv. modifikátorů. Jsou to klíčová slova jazyka Java, která umožňují „skrýt“ proměnnou před vnějším světem či ostatními třídami. Není-li proměnná či metoda dostupná, nelze k ní přístupovat (číst, zapisovat, volat). Seznam všech modifikátorů a jejich efekt na viditelnost proměnných a metod uvádí následující tabulka:
| Modifikátor | Třída | Balíček | Potomek | Okolní svět |
|---|---|---|---|---|
| public | Ano | Ano | Ano | Ano |
| protected | Ano | Ano | Ano | Ne |
| (bez modifikátoru) | Ano | Ano | Ne | Ne |
| private | Ano | Ne | Ne | Ne |
Kvalifikátory
- final
- u třídy: tato třída nemůže mít potomky
- u metody: tuto metodu již nelze v podtřídách dále upravovat
- u atributu: do tohoto atributu lze přiřadit hodnotu pouze jednou
- u proměnné: do této proměnné lze přiřadit hodnotu pouze jednou
- u parametru metody: tento parametr nebude v těle metody změněn
- volatile
- u atributu: atribut může být současně modifikován více vlákny a tak je zakázáno jej uchovávat ve vyrovnávací paměti (cache)
- transient
- u atributu: tento atribut nebude uložen při serializaci (převod objektu na tok bytů, který lze uložit do souboru nebo přenést přes síť)
- synchronized
- u bloku: do tohoto bloku může najednou vstoupit pouze jedno vlákno (mutex)
- u metody: do této metody může najednou vstoupit pouze jedno vlákno (mutex)
- native
- u metody: metoda je implementována v jiném jazyce než Java (např. C, C++)
Edice Javy
Java přichází v několika edicích, které se liší knihovnou tříd a podporou některých funkcí.
- Java Card – pro „chytré“ čipové karty
- Java Platform Micro Edition (Java ME) — platformy s omezenými prostředky (mobilní telefony, GPS)
- Java Platform Standard Edition (Java SE) — standardní desktopové aplikace
- Java Platform Enterprise Edition (Java EE) — internetové aplikace a distribuované prostředí
Tipy a triky
Assertion
V kódu lze používat speciální makro assert, které za běhu kontroluje platnost zadaného pravdivostního výrazu. Pokud není výraz splněn, program vyvolá výjimku AssertionError, která programátorovi pomůže identifikovat místo, kde k selhání došlo. Makra assert je nutné aktivovat argumentem -ea (enable assertion), který se předá virtuálnímu stroji Javy (JVM) při spuštění programu (v IDE k tomuto účelu bývá speciální textové pole „Runtime Arguments“).
Obecně se nedoporučuje používat makro assert pro kontrolu vstupů. K tomu by měly sloužit výjimky, které umožní zbytku programu na nečekanou situaci rozumně reagovat. Makro by tedy mělo být použito opravdu jen pro kontrolu situací, které by „neměly nikdy nastat“. V praxi se osvědčilo používat spíše větší množství assertů s kratšími logickými výrazy, aby v případě chyby neslo nahlášené číslo řádku dostatečnou informaci o tom, co se vlastně stalo.
{
final int result = (int) (part / whole);
assert (result >= 0);
assert (result <= 100);
return result;
}
zdrojový kód (Java) - zobrazit (172 znaků)
Komunikace přes TCP
Síťová komunikace založená na socketech se v Javě implementuje velmi jednoduše. Následující příklad demonstruje odeslání jednoho čísla „42“ přes TCP a jeho vypsání na straně serveru.
Server
{
// vytvořit serverový socket na portu 12345
final ServerSocket serverSocket = new ServerSocket (12345);
// čekat, dokud se klient nepřipojí a pak získat jeho socket
final Socket clientSocket = serverSocket.accept ();
// získat vstupní proud socketu
// (výstup pro klienta = vstup pro server)
final DataInputStream clientStream = new DataInputStream (clientSocket.getInputStream ());
// načíst data
System.out.println ("Received number: " + clientStream.readInt ());
// uvolnit prostředky
clientStream.close ();
clientSocket.close ();
}
catch (final IOException e)
{
System.out.println ("Server I/O error: " + e.getMessage ());
}
zdrojový kód (Java) - zobrazit (669 znaků)
Klient
{
// vytvořit socket a spojit ho se serverem "localhost" na portu 12345
final Socket clientSocket = new Socket ("localhost", 12345);
// získat výstupní proud socketu
// (výstup pro klienta = vstup pro server)
final DataOutputStream clientStream = new DataOutputStream (clientSocket.getOutputStream ());
// odeslat data
clientStream.writeInt (42);
// uvolnit prostředky
clientStream.close ();
clientSocket.close ();
}
catch (final UnknownHostException e)
{
System.out.println ("Client unknown host error: " + e.getMessage ());
}
catch (final IOException e)
{
System.out.println ("Client I/O error: " + e.getMessage ());
}
zdrojový kód (Java) - zobrazit (655 znaků)