Syntaxe Java - Java syntax
Syntax z Javy odkazuje na soubor pravidel určujících, jak je Java program psaný a interpretována.
Syntaxe je většinou odvozena z C a C ++ . Na rozdíl od C ++ v Javě neexistují žádné globální funkce nebo proměnné, ale existují datové členy, které jsou také považovány za globální proměnné . Veškerý kód patří do tříd a všechny hodnoty jsou objekty . Jedinou výjimkou jsou primitivní typy , které nejsou reprezentovány instancí třídy z důvodů výkonu (i když je lze automaticky převádět na objekty a naopak prostřednictvím autoboxingu ). Některé funkce, jako je přetížení operátoru nebo typy celých čísel bez znaménka, jsou vynechány, aby se zjednodušil jazyk a zabránilo se možným chybám při programování.
Syntaxe Java byla postupně rozšiřována v průběhu řady hlavních vydání JDK a nyní podporuje funkce, jako je generické programování a literály funkcí (v jazyce Java se nazývají výrazy lambda). Od roku 2017 vychází nová verze JDK dvakrát ročně, přičemž každé vydání přináší postupná vylepšení jazyka.
Základy
Identifikátor
Identifikátor je název prvku v kódu . Při výběru názvů prvků je třeba dodržovat určité standardní konvence pojmenování . Identifikátory v Javě rozlišují velká a malá písmena .
Identifikátor může obsahovat:
- Libovolný znak Unicode, který je písmeno (včetně číselných písmen, jako jsou římské číslice ) nebo číslice.
- Znak měny (například ¥).
- Spojovací znak interpunkce (například _ ).
Identifikátor nemůže:
- Začněte číslicí.
- Rovná se vyhrazenému klíčovému slovu, null literálu nebo boolean literálu.
Klíčová slova
| abstraktní | pokračovat | pro | Nový | přepínač |
| tvrdit | výchozí | jít do | balík | synchronizovány |
| booleovský | dělat | -li | soukromé | tento |
| přestávka | dvojnásobek | nářadí | chráněný | házet |
| byte | jiný | import | veřejnost | hází |
| případ | enum | příklad | vrátit se | přechodné |
| úlovek | rozšiřuje | int | krátký | Snaž se |
| char | finále | rozhraní | statický | var |
| třída | Konečně | dlouho | strictfp | prázdné |
| konst | plovák | rodák | super | nestálý |
| zatímco |
Literály
| Celá čísla | |
|---|---|
| binární (zavedeno v Java SE 7) | 0b11110101 ( 0b následované binárním číslem) |
| osmičkové | 0365 ( 0 následované osmičkovým číslem) |
| hexadecimální | 0xF5 ( 0x následované šestnáctkovým číslem) |
| desetinný | 245 (desetinné číslo) |
| Hodnoty s plovoucí desetinnou čárkou | |
| plovák | 23,5F , 0,5f , 1,72E3F (desetinný zlomek s volitelným indikátorem exponent, následovaný F ) |
| 0x.5FP0F , 0x.5P-6f ( 0x následovaný hexadecimálním zlomkem s povinným indikátorem exponentu a příponou F ) | |
| dvojnásobek | 23,5D , 0,5 , 1,72E3D (desetinný zlomek s volitelným indikátorem exponent, následovaný volitelným D ) |
| 0x.5FP0 , 0x.5P-6D ( 0x následovaný hexadecimálním zlomkem s indikátorem povinného exponentu a volitelnou příponou D ) | |
| Doslovné znaky | |
| char | 'a' , 'Z' , '\ u0231' (znak nebo znak únik, uzavřený v jednoduchých uvozovkách) |
| Booleovské literály | |
| booleovský | pravda , lež |
| null doslovný | |
| nulová reference | nula |
| Řetězcové literály | |
| Tětiva | „Hello, World“ (sekvence znaků a úniků znaků uzavřená do uvozovek) |
| Postavy unikají v řetězcích | |
| Unicode znak | \ u3876 ( \ u následovaný hexadecimálním bodem unicode kódu až do U+FFFF) |
| Osmičkový útěk | \ 352 (osmičkové číslo nepřesahující 377, předchází zpětné lomítko) |
| Line feed | \ n |
| Návrat vozíku | \ r |
| Formulář | \F |
| Obrácené lomítko | \\ |
| Jediný citát | \ ' |
| Dvojitá citace | \ " |
| Tab | \ t |
| Backspace | \ b |
Celočíselné literály jsou ve intvýchozím nastavení longtypu, pokud typ není určen připojením Lnebo lpříponou k literálu, např 367L. Od verze Java SE 7 je možné zahrnout podtržítka mezi číslice čísla, aby se zvýšila čitelnost; například číslo 145608987 lze zapsat jako 145_608_987 .
Proměnné
Proměnné jsou identifikátory spojené s hodnotami. Jsou deklarovány zapsáním typu a názvu proměnné a jsou volitelně inicializovány ve stejném příkazu přiřazením hodnoty.
int count; //Declaring an uninitialized variable called 'count', of type 'int'
count = 35; //Initializing the variable
int count = 35; //Declaring and initializing the variable at the same time
Více proměnných stejného typu lze deklarovat a inicializovat v jednom příkazu pomocí čárky jako oddělovače.
int a, b; //Declaring multiple variables of the same type
int a = 2, b = 3; //Declaring and initializing multiple variables of the same type
Od verze Java 10 je možné automaticky odvozovat typy pro proměnné pomocí var.
// stream will have the FileOutputStream type as inferred from its initializer
var stream = new FileOutputStream("file.txt");
// An equivalent declaration with an explicit type
FileOutputStream stream = new FileOutputStream("file.txt");
Bloky kódu
Oddělovače { a} znamenat blok kódu a nový rozsah. Členové třídy a tělo metody jsou příklady toho, co může žít v těchto závorkách v různých kontextech.
Uvnitř těl metod lze k vytvoření nových rozsahů použít závorky, a to následovně:
void doSomething() {
int a;
{
int b;
a = 1;
}
a = 2;
b = 3; // Illegal because the variable b is declared in an inner scope..
}
Komentáře
Java má tři druhy komentářů: tradiční komentáře , komentáře na konci řádku a komentáře k dokumentaci .
Tradiční komentáře, známé také jako blokové komentáře, začínají /*a končí */, mohou přesahovat na více řádků. Tento typ komentáře byl odvozen z jazyků C a C ++.
/* This is a multi-line comment.
It may occupy more than one line. */
Komentáře //na konci řádku začínají a končí až na konci aktuálního řádku. Tento typ komentáře je také v C ++ a v moderním C.
// This is an end-of-line comment
Komentáře k dokumentaci ve zdrojových souborech jsou zpracovávány nástrojem Javadoc pro generování dokumentace. Tento typ komentáře je identický s tradičními komentáři, kromě toho, že začíná /**konvencemi definovanými nástrojem Javadoc a dodržuje je. Technicky jsou tyto komentáře zvláštním druhem tradičních komentářů a nejsou specificky definovány v jazykové specifikaci.
/**
* This is a documentation comment.
*
* @author John Doe
*/
Univerzální typy
Třídy v balíčku java.lang jsou implicitně importovány do každého programu, pokud žádné explicitně importované typy nemají stejné názvy. Mezi důležité patří:
- java.lang.Object
- Nejlepší typ Javy . Nadtřída všech tříd, které nedeklarují nadřazenou třídu. Všechny hodnoty lze převést na tento typ, i když u primitivních hodnot to zahrnuje autobox .
- java.lang.String
- Základní typ řetězce Java. Neměnný . Některé metody považují každou kódovou jednotku UTF-16 za „znak“, ale jsou k dispozici také metody pro převod na
int[]efektivně UTF-32 . - java.lang.Throwable
- supertyp všeho, co lze házet nebo chytit pomocí Java
throwacatchpříkazů.
Struktura programu
Java aplikace se skládají ze sbírek tříd. Třídy existují v balíčcích, ale mohou být také vnořeny do jiných tříd.
main metoda
Každá aplikace Java musí mít vstupní bod. To platí jak pro aplikace grafického rozhraní, tak pro aplikace konzoly. Vstupním bodem je mainmetoda. mainMetoda může mít více než jednu třídu , ale hlavní třída je vždy definována externě (například v souboru manifestu ). Metoda musí být statica je předána argumenty příkazového řádku jako pole řetězců. Na rozdíl od C ++ nebo C# nikdy nevrací hodnotu a musí se vracet void.
public static void main(String[] args) {
}
Balíčky
Balíčky jsou součástí názvu třídy a používají se ke seskupení a/nebo rozlišení pojmenovaných entit od ostatních. Dalším účelem balíčků je řídit přístup ke kódu společně s modifikátory přístupu. Například java.io.InputStreamje plně kvalifikovaný název třídy pro třídu, InputStreamkterá se nachází v balíčku java.io.
Balíček je deklarován na začátku souboru s packagedeklarací:
package myapplication.mylibrary;
public class MyClass {
}
Třídy s publicmodifikátorem musí být umístěny do souborů se stejným názvem a příponou java a vloženy do vnořených složek odpovídajících názvu balíčku. Výše uvedená třída myapplication.mylibrary.MyClassbude mít následující cestu: myapplication/mylibrary/MyClass.java.
Dovozní prohlášení
Zadejte dovozní prohlášení
Deklarace importu typu umožňuje odkazovat na pojmenovaný typ jednoduchým jménem, a nikoli celým názvem, který obsahuje balíček. Importní deklarace mohou být importní deklarace jednoho typu nebo deklarace importu na vyžádání . Po deklaraci balíčku musí být importní deklarace umístěna na začátek souboru kódu.
package myPackage;
import java.util.Random; // Single type declaration
public class ImportsTest {
public static void main(String[] args) {
/* The following line is equivalent to
* java.util.Random random = new java.util.Random();
* It would've been incorrect without the import.
*/
Random random = new Random();
}
}
Deklarace importu na vyžádání jsou uvedeny v kódu. „Typový import“ importuje všechny typy balíčku. "Statický import" importuje členy balíčku.
import java.util.*; /*This form of importing classes makes all classes
in package java.util available by name, could be used instead of the
import declaration in the previous example. */
import java.*; /*This statement is legal, but does nothing, since there
are no classes directly in package java. All of them are in packages
within package java. This does not import all available classes.*/
Statické dovozní prohlášení
Tento typ deklarace je k dispozici od J2SE 5.0 . Statická deklarace importu umožňuje přístup ke statickým členům definovaným v jiné třídě, rozhraní, anotaci nebo výčtu; bez zadání názvu třídy:
import static java.lang.System.out; //'out' is a static field in java.lang.System
public class HelloWorld {
public static void main(String[] args) {
/* The following line is equivalent to:
System.out.println("Hi World!");
and would have been incorrect without the import declaration. */
out.println("Hello World!");
}
}
Deklarace importu na vyžádání umožňují importovat všechna pole typu:
import static java.lang.System.*;
/* This form of declaration makes all
fields in the java.lang.System class available by name, and may be used instead
of the import declaration in the previous example. */
Konstantní výčty lze také použít se statickým importem. Tento výčet je například v balíčku s názvem screen:
public enum ColorName {
RED, BLUE, GREEN
};
K načtení konstant výčtu je možné použít statické deklarace importu v jiné třídě:
import screen.ColorName;
import static screen.ColorName.*;
public class Dots {
/* The following line is equivalent to 'ColorName foo = ColorName.RED',
and it would have been incorrect without the static import. */
ColorName foo = RED;
void shift() {
/* The following line is equivalent to:
if (foo == ColorName.RED) foo = ColorName.BLUE; */
if (foo == RED) foo = BLUE;
}
}
Operátoři
Operátory v Javě jsou podobné těm v C ++ . Kvůli mechanismům sběru odpadků v Javě však neexistuje žádný deleteoperátor a s ukazateli se neprovádějí žádné operace, protože je Java nepodporuje. Další rozdíl je v tom, že Java má nepodepsaný operátor pravého posunu ( ), zatímco podpis operátora pravého posunu C je závislý na typu. Operátory v Javě nelze přetížit .
>>>
| Přednost | Operátor | Popis | Asociativita |
|---|---|---|---|
| 1 |
()
|
Vyvolání metody | Zleva do prava |
[]
|
Přístup k poli | ||
.
|
Výběr členů třídy | ||
| 2 |
++ --
|
Přírůstek a úbytek postfixu | |
| 3 |
++ --
|
Přírůstek a úbytek předpony | Zprava doleva |
+ -
|
Unární plus a mínus | ||
! ~
|
Logické NE a bitové NE | ||
(type) val
|
Zadejte obsazení | ||
new
|
Vytvoření instance třídy nebo pole | ||
| 4 |
* / %
|
Násobení, dělení a modul (zbytek) | Zleva do prava |
| 5 |
+ -
|
Sčítání a odčítání | |
+
|
Zřetězení řetězců | ||
| 6 |
<< >> >>>
|
Bitový levý posun, podepsaný pravý posun a nepodepsaný pravý posun | |
| 7 |
< <=
|
Relační „méně než“ a „méně než nebo rovno“ | |
> >=
|
Relační „větší než“ a „větší než nebo rovno“ | ||
instanceof
|
Porovnání typů | ||
| 8 |
== !=
|
Relační „rovná se“ a „není rovno“ | |
| 9 |
&
|
Bitové a logické AND | |
| 10 |
^
|
Bitový a logický XOR (exkluzivní nebo) | |
| 11 |
|
|
Bitové a logické NEBO (včetně nebo) | |
| 12 |
&&
|
Logické podmíněné-AND | |
| 13 |
||
|
Logické podmíněné-NEBO | |
| 14 |
c ? t : f
|
Ternární podmíněný (viz :? ) | Zprava doleva |
| 15 |
=
|
Jednoduché zadání | |
+= -=
|
Přiřazení součtem a rozdílem | ||
*= /= %=
|
Přiřazení podle produktu, podílu a zbytku | ||
<<= >>= >>>=
|
Přiřazení bitovým posunem doleva, podepsaným pravým posunem a nepodepsaným pravým posunem | ||
&= ^= |=
|
Přiřazení bitovým AND, XOR a OR |
Řídicí struktury
Podmíněné výroky
if tvrzení
pokud jsou příkazy v Javě podobné těm v C a používají stejnou syntaxi:
if (i == 3) doSomething();
ifpříkaz může obsahovat volitelný elseblok, v takovém případě se stane příkazem if-then-else:
if (i == 2) {
doSomething();
} else {
doSomethingElse();
}
Stejně jako C, else-if konstrukce neobsahuje žádná speciální klíčová slova, je vytvořena jako sekvence samostatných příkazů if-then-else:
if (i == 3) {
doSomething();
} else if (i == 2) {
doSomethingElse();
} else {
doSomethingDifferent();
}
Všimněte si také, že místo jednoduchého příkazu if lze použít například operátor ?:
int a = 1;
int b = 2;
int minVal = (a < b) ? a : b;
switch tvrzení
Switch v Javě lze použít byte, short, chara int(poznámka: ne long) primitivní datové typy, nebo jejich odpovídající typy obálky. Počínaje J2SE 5.0 je možné použít typy výčtu . Počínaje jazykem Java SE 7 je možné používat řetězce. Jiné typy odkazů nelze použít v switchpříkazech.
Možné hodnoty jsou uvedeny pomocí caseštítků. Tyto štítky v Javě mohou obsahovat pouze konstanty (včetně konstant výčtu a řetězcových konstant). Provádění začne po označení odpovídajícímu výrazu v závorkách. defaultMůže být přítomen volitelný štítek, který deklaruje, že kód následující za ním bude spuštěn, pokud žádný z označení případu neodpovídá výrazu.
Kód pro každý štítek končí breakklíčovým slovem. Je možné jej vynechat, což způsobí, že provádění přejde na další štítek, během kompilace však bude obvykle hlášeno varování.
switch (ch) {
case 'A':
doSomething(); // Triggered if ch == 'A'
break;
case 'B':
case 'C':
doSomethingElse(); // Triggered if ch == 'B' or ch == 'C'
break;
default:
doSomethingDifferent(); // Triggered in any other case
break;
}
switch výrazy
Od verze Java 14 je možné používat výrazy přepínačů, které používají novou syntaxi šipek:
var result = switch (ch) {
case 'A' -> Result.GREAT;
case 'B', 'C' -> Result.FINE;
default -> throw new ThisIsNoGoodException();
};
Alternativně existuje možnost vyjádřit totéž s yieldpříkazem, ačkoli se doporučuje upřednostňovat syntaxi šipek, protože se tím vyhnete problému náhodného propadnutí.
var result = switch (ch) {
case 'A':
yield Result.GREAT;
case 'B':
case 'C':
yield Result.FINE;
default:
throw new ThisIsNoGoodException();
};
Iterační prohlášení
Iterační příkazy jsou příkazy, které jsou opakovaně prováděny, když je daná podmínka vyhodnocena jako pravdivá. Od J2SE 5.0 má Java čtyři formy takových příkazů.
while smyčka
Ve whilesmyčce se test provádí před každou iterací.
while (i < 10) {
doSomething();
}
do ... while smyčka
Ve do ... whilesmyčce se test provádí po každé iteraci. V důsledku toho je kód vždy spuštěn alespoň jednou.
// doSomething() is called at least once
do {
doSomething();
} while (i < 10);
for smyčka
forsmyčky v Javě zahrnují inicializátor, podmínku a výraz čítače. Je možné zahrnout několik výrazů stejného druhu pomocí čárky jako oddělovače (kromě podmínky). Na rozdíl od C je však čárka pouze oddělovač a nikoli operátor.
for (int i = 0; i < 10; i++) {
doSomething();
}
// A more complex loop using two variables
for (int i = 0, j = 9; i < 10; i++, j -= 3) {
doSomething();
}
Stejně jako C jsou všechny tři výrazy volitelné. Následující smyčka je nekonečná:
for (;;) {
doSomething();
}
Vylepšená forsmyčka
Vylepšené forsmyčky jsou k dispozici od J2SE 5.0 . Tento typ smyčky používá k vrácení každé položky v dané kolekci vestavěné iterátory přes pole a kolekce. Každý prvek je vrácen a dosažitelný v kontextu bloku kódu. Po spuštění bloku se vrátí další položka, dokud nezůstanou žádné položky. Na rozdíl od C# tento druh smyčky nezahrnuje speciální klíčové slovo, ale místo toho používá jiný styl zápisu.
for (int i : intArray) {
doSomething(i);
}
Skoková prohlášení
Štítky
Štítky jsou označeny body v kódu použitém příkazy breaka continue. gotoKlíčové slovo Java nelze použít k přeskočení na konkrétní body v kódu.
start:
someMethod();
break tvrzení
Příkaz se breakvymyká nejbližší smyčce nebo switchpříkazu. Provádění pokračuje v příkazu po ukončeném příkazu, pokud existuje.
for (int i = 0; i < 10; i++) {
while (true) {
break;
}
// Will break to this point
}
Je možné se vymanit z vnější smyčky pomocí štítků:
outer:
for (int i = 0; i < 10; i++) {
while (true) {
break outer;
}
}
// Will break to this point
continue tvrzení
Příkaz continuepřeruší aktuální iteraci aktuálního ovládacího příkazu a zahájí další iteraci. Následující whilesmyčka v níže uvedeném kódu čte znaky voláním getChar()a přeskakuje příkazy v těle smyčky, pokud jsou znaky mezery:
int ch;
while (ch == getChar()) {
if (ch == ' ') {
continue; // Skips the rest of the while-loop
}
// Rest of the while-loop, will not be reached if ch == ' '
doSomething();
}
Štítky lze specifikovat v continueprohlášeních a breakprohlášeních:
outer:
for (String str : stringsArr) {
char[] strChars = str.toCharArray();
for (char ch : strChars) {
if (ch == ' ') {
/* Continues the outer cycle and the next
string is retrieved from stringsArr */
continue outer;
}
doSomething(ch);
}
}
return tvrzení
Příkaz returnslouží k ukončení provádění metody a vrácení hodnoty. Hodnota vrácená metodou je zapsána za returnklíčové slovo. Pokud metoda vrací cokoli jiného než void, musí použít returnpříkaz k vrácení nějaké hodnoty.
void doSomething(boolean streamClosed) {
// If streamClosed is true, execution is stopped
if (streamClosed) {
return;
}
readFromStream();
}
int calculateSum(int a, int b) {
int result = a + b;
return result;
}
returnpříkaz okamžitě ukončí provádění, s výjimkou jednoho případu: pokud je příkaz nalezen v trybloku a je doplněn o finally, je do finallybloku předáno řízení .
void doSomething(boolean streamClosed) {
try {
if (streamClosed) {
return;
}
readFromStream();
} finally {
/* Will be called last even if
readFromStream() was not called */
freeResources();
}
}
Prohlášení o zpracování výjimek
try-catch-finally prohlášení
Výjimky jsou spravovány v rámci try... catchbloků.
try {
// Statements that may throw exceptions
methodThrowingExceptions();
} catch (Exception ex) {
// Exception caught and handled here
reportException(ex);
} finally {
// Statements always executed after the try/catch blocks
freeResources();
}
Provádějí se příkazy v trybloku a pokud některý z nich vyvolá výjimku, provádění bloku se přeruší a výjimku zpracuje catchblok. Může existovat více catchbloků, v takovém případě se provede první blok s proměnnou výjimky, jejíž typ odpovídá typu vyvolané výjimky.
Java SE 7 také zavedla klauzule multi-catch kromě klauzulí uni-catch. Tento typ klauzulí catch umožňuje Javě zpracovávat různé typy výjimek v jednom bloku za předpokladu, že nejsou navzájem podtřídami.
try {
methodThrowingExceptions();
} catch (IOException | IllegalArgumentException ex) {
//Both IOException and IllegalArgumentException will be caught and handled here
reportException(ex);
}
Pokud se žádný catchtyp shoduje s typem vyvolané výjimky, provádění vnějšího bloku (nebo metody) obsahujícího try... catchpříkaz se přeruší a výjimka se předá nahoru a mimo obsahující blok (nebo metodu). Výjimka se šíří vzhůru prostřednictvím zásobníku volání, dokud catchse v rámci jedné z aktuálně aktivních metod nenajde odpovídající blok. Pokud se výjimka šíří až po nejlepší mainmetodu, aniž by catchbyl nalezen odpovídající blok, je do standardního výstupního proudu zapsán textový popis výjimky.
Příkazy v finallybloku jsou vždy provedeny po blocích trya catch, bez ohledu na to, zda byla vyvolána výjimka, ai když returnbylo dosaženo příkazu. Takové bloky jsou užitečné pro poskytování vyčištění kódu, který je zaručeno, že bude vždy spuštěn.
catchA finallybloky jsou volitelné, ale alespoň jeden nebo druhý musí být přítomen po trybloku.
try-prohlášení o zdrojích
tryPříkazy -with-resources jsou speciální typ try-catch-finallypříkazů zavedených jako implementace vzoru Dispose v Java SE 7. V trypříkazu -with-resources je za tryklíčovým slovem inicializace jednoho nebo více zdrojů, které se automaticky uvolní při spuštění trybloku je dokončena. Zdroje se musí implementovat java.lang.AutoCloseable. tryNa rozdíl od běžných příkazů se nevyžaduje, aby příkazy -with-resources měly a catchnebo finallyblock try-catch-finally.
try (FileOutputStream fos = new FileOutputStream("filename");
XMLEncoder xEnc = new XMLEncoder(fos)) {
xEnc.writeObject(object);
} catch (IOException ex) {
Logger.getLogger(Serializer.class.getName()).log(Level.SEVERE, null, ex);
}
Od Javy 9 je možné používat již deklarované proměnné:
FileOutputStream fos = new FileOutputStream("filename");
XMLEncoder xEnc = new XMLEncoder(fos);
try (fos; xEnc) {
xEnc.writeObject(object);
} catch (IOException ex) {
Logger.getLogger(Serializer.class.getName()).log(Level.SEVERE, null, ex);
}
throw tvrzení
Příkaz throwslouží k vyvolání výjimky a ukončení provádění bloku nebo metody. Instance vyvolané výjimky je zapsána za throwpříkazem.
void methodThrowingExceptions(Object obj) {
if (obj == null) {
// Throws exception of NullPointerException type
throw new NullPointerException();
}
// Will not be called, if object is null
doSomethingWithObject(obj);
}
Ovládání souběžnosti vláken
Java má vestavěné nástroje pro vícevláknové programování . Pro účely synchronizace vláken je synchronizedprohlášení obsaženo v jazyce Java.
Aby byl blok kódu synchronizován, předchází mu synchronizedklíčové slovo následované objektem zámku v závorkách. Když provádějící vlákno dosáhne synchronizovaného bloku, získá zámek vzájemného vyloučení , spustí blok a poté zámek uvolní. Do tohoto bloku nesmí vstoupit žádná vlákna, dokud zámek neuvolníte. Jako zámek lze použít jakýkoli nenulový referenční typ.
/* Acquires lock on someObject. It must be of
a reference type and must be non-null */
synchronized (someObject) {
// Synchronized statements
}
assert tvrzení
assertprohlášení jsou k dispozici od J2SE 1.4 . Tyto typy příkazů se používají k vytváření tvrzení ve zdrojovém kódu, které lze zapnout a vypnout během provádění pro konkrétní třídy nebo balíčky. K deklaraci tvrzení se použije assertklíčové slovo následované podmíněným výrazem. Pokud vyhodnotí, falsekdy je příkaz spuštěn, je vyvolána výjimka. Toto prohlášení může obsahovat dvojtečku následovanou dalším výrazem, který bude fungovat jako zpráva podrobností výjimky.
// If n equals 0, AssertionError is thrown
assert n != 0;
/* If n equals 0, AssertionError will be thrown
with the message after the colon */
assert n != 0 : "n was equal to zero";
Primitivní typy
Primitivní typy v Javě zahrnují celočíselné typy, čísla s plovoucí desetinnou čárkou, kódové jednotky UTF-16 a logický typ. V Javě neexistují žádné nepodepsané typy kromě chartypu, který se používá k reprezentaci kódových jednotek UTF-16. Nedostatek nepodepsaných typů je kompenzován zavedením nepodepsané operace pravého posunu ( >>>), která v C ++ není k dispozici. Přesto byla kritizována nedostatek kompatibility s C a C ++, který to způsobuje.
| Primitivní typy | |||||
|---|---|---|---|---|---|
| Zadejte název | Wrapper třída | Hodnota | Rozsah | Velikost | Výchozí hodnota |
byte
|
java.lang.Byte
|
celé číslo | −128 až +127 | 8bitový (1 bajt) |
0
|
short
|
java.lang.Short
|
celé číslo | −32 768 až +32 767 | 16bitový (2bajtový) |
0
|
int
|
java.lang.Integer
|
celé číslo | −2,147,483,648 až +2,147,483,647 | 32bitový (4bajtový) |
0
|
long
|
java.lang.Long
|
celé číslo | −9,223,372,036,854,775,808 až +9,223,372,036,854,775,807 |
64bitový (8bajtový) |
0
|
float
|
java.lang.Float
|
číslo s plovoucí desetinnou čárkou | ± 1,401298E − 45 až ± 3,402823E+38 | 32bitový (4bajtový) |
0.0f
|
double
|
java.lang.Double
|
číslo s plovoucí desetinnou čárkou | ± 4,94065645841246E − 324 až ± 1,79769313486232E+308 |
64bitový (8bajtový) |
0.0
|
boolean
|
java.lang.Boolean
|
Boolean |
true nebo false
|
1bitový (1bitový) |
false
|
char
|
java.lang.Character
|
Jednotka kódu UTF-16 ( znak BMP nebo část náhradního páru) |
'\u0000' přes '\uFFFF'
|
16bitový (2bajtový) |
'\u0000'
|
charnemusí nutně odpovídat jedinému znaku. Může představovat část náhradního páru , v takovém případě je bod kódu Unicode reprezentován posloupností dvou charhodnot.
Box a unboxing
Tato jazyková funkce byla představena v J2SE 5.0 . Box je operace převodu hodnoty primitivního typu na hodnotu odpovídajícího referenčního typu, která slouží jako obal pro tento konkrétní primitivní typ. Unboxing je obrácená operace převodu hodnoty referenčního typu (dříve v rámečku) na hodnotu odpovídajícího primitivního typu. Žádná operace nevyžaduje explicitní převod.
Příklad:
int foo = 42; // Primitive type
Integer bar = foo; /* foo is boxed to bar, bar is of Integer type,
which serves as a wrapper for int */
int foo2 = bar; // Unboxed back to primitive type
Referenční typy
Mezi referenční typy patří typy tříd, typy rozhraní a typy polí. Při volání konstruktoru se na haldě vytvoří objekt a proměnné se přiřadí odkaz. Když se proměnná objektu dostane mimo rozsah, odkaz se přeruší a pokud nezůstanou žádné odkazy, objekt bude označen jako odpadky. Popelář je pak po nějaké době sebere a zničí.
Referenční proměnná je, nullkdyž neodkazuje na žádný objekt.
Pole
Pole v Javě se vytvářejí za běhu, stejně jako instance třídy. Délka pole je definována při vytváření a nelze ji změnit.
int[] numbers = new int[5];
numbers[0] = 2;
numbers[1] = 5;
int x = numbers[0];
Inicializátory
// Long syntax
int[] numbers = new int[] {20, 1, 42, 15, 34};
// Short syntax
int[] numbers2 = {20, 1, 42, 15, 34};
Vícerozměrná pole
V Javě jsou vícerozměrná pole reprezentována jako pole polí. Technicky jsou reprezentovány poli odkazů na jiná pole.
int[][] numbers = new int[3][3];
numbers[1][2] = 2;
int[][] numbers2 = {{2, 3, 2}, {1, 2, 6}, {2, 4, 5}};
Vzhledem k povaze vícerozměrných polí se dílčí pole mohou lišit v délce, takže vícerozměrná pole nemusí být na rozdíl od C obdélníková:
int[][] numbers = new int[2][]; //Initialization of the first dimension only
numbers[0] = new int[3];
numbers[1] = new int[2];
Třídy
Třídy jsou základy objektově orientovaného jazyka, jako je Java. Obsahují členy, kteří ukládají a manipulují s daty. Třídy jsou rozděleny na nejvyšší úroveň a vnořené . Vnořené třídy jsou třídy umístěné uvnitř jiné třídy, které mohou přistupovat k soukromým členům uzavřené třídy. Vnořené třídy zahrnují členské třídy (které lze definovat pomocí statického modifikátoru pro jednoduché vnoření nebo bez něj pro vnitřní třídy), místní třídy a anonymní třídy .
Prohlášení
| Třída nejvyšší úrovně |
class Foo {
// Class members
}
|
|---|---|
| Vnitřní třída |
class Foo { // Top-level class
class Bar { // Inner class
}
}
|
| Vnořená třída |
class Foo { // Top-level class
static class Bar { // Nested class
}
}
|
| Místní třída |
class Foo {
void bar() {
class Foobar {// Local class within a method
}
}
}
|
| Anonymní třída |
class Foo {
void bar() {
new Object() {// Creation of a new anonymous class extending Object
};
}
}
|
Instance
Nestatické členy třídy definují typy proměnných a metod instance , které souvisejí s objekty vytvořenými z této třídy. K vytvoření těchto objektů musí být třída vytvořena pomocí newoperátoru a volání konstruktoru třídy.
Foo foo = new Foo();
Přístup ke členům
K členům obou instancí a statických tříd se přistupuje pomocí .(tečkového) operátoru.
Přístup k členovi
instance Ke členům instance lze přistupovat prostřednictvím názvu proměnné.
String foo = "Hello";
String bar = foo.toUpperCase();
Přístup ke členu statické třídy Ke
statickým členům se přistupuje pomocí názvu třídy nebo jiného typu. To nevyžaduje vytvoření instance třídy. Statické členy jsou deklarovány pomocí staticmodifikátoru.
public class Foo {
public static void doSomething() {
}
}
// Calling the static method
Foo.doSomething();
Modifikátory
Modifikátory jsou klíčová slova používaná k úpravě deklarací typů a členů typu. Nejpozoruhodnější je, že existuje podskupina obsahující modifikátory přístupu.
-
abstract- Určuje, že třída slouží pouze jako základní třída a nelze ji vytvořit. -
static- Používá se pouze pro členské třídy, určuje, že členská třída nepatří do konkrétní instance obsahující třídy. -
final- Třídy označené jakofinalnelze rozšiřovat a nemohou mít žádné podtřídy. -
strictfp- Určuje, že všechny operace s plovoucí desetinnou čárkou musí být prováděny v souladu s IEEE 754 a zakazuje používání zvýšené přesnosti pro ukládání mezivýsledků.
Modifikátory přístupu
Tyto modifikátory přístupu , nebo modifikátory dědičnosti nastavit přístupnost tříd, metod a ostatních členů. Členy označené jako publiclze kontaktovat odkudkoli. Pokud třída nebo její člen nemá žádné modifikátory, předpokládá se výchozí přístup.
public class Foo {
int go() {
return 0;
}
private class Bar {
}
}
Následující tabulka ukazuje, zda má kód v rámci třídy přístup ke třídě nebo metodě v závislosti na umístění přístupové třídy a modifikátoru pro přístupovou třídu nebo člena třídy:
| Modifikátor | Stejná třída nebo vnořená třída | Další třída uvnitř stejného balíčku | Rozšířená třída v jiném balíčku | V jiném balíčku není rozšířeno |
|---|---|---|---|---|
private
|
Ano | Ne | Ne | Ne |
| výchozí (balíček soukromý) | Ano | Ano | Ne | Ne |
protected
|
Ano | Ano | Ano | Ne |
public
|
Ano | Ano | Ano | Ano |
Konstruktory a inicializátory
Konstruktér je speciální metoda volána, když je objekt inicializovat. Jeho účelem je inicializovat členy objektu. Hlavní rozdíly mezi konstruktory a běžnými metodami jsou v tom, že konstruktory jsou volány pouze tehdy, když je vytvořena instance třídy a nikdy nic nevracejí. Konstruktory jsou deklarovány jako běžné metody, ale jsou pojmenovány podle třídy a není určen žádný návratový typ:
class Foo {
String str;
Foo() { // Constructor with no arguments
// Initialization
}
Foo(String str) { // Constructor with one argument
this.str = str;
}
}
Inicializátory jsou bloky kódu, které se provádějí při vytvoření třídy nebo instance třídy. Existují dva druhy inicializátorů, statické inicializátory a inicializátory instancí .
Statické inicializátory inicializují statická pole při vytvoření třídy. Jsou deklarovány pomocí staticklíčového slova:
class Foo {
static {
// Initialization
}
}
Třída je vytvořena pouze jednou. Proto se statické inicializátory nevolají více než jednou. Naopak, inicializátory instance jsou automaticky volány před voláním konstruktoru pokaždé, když je vytvořena instance třídy. Na rozdíl od konstruktorů nemohou inicializátoři instance přijímat žádné argumenty a obecně nemohou vyvolat žádné zaškrtnuté výjimky (kromě několika speciálních případů). Inicializátory instance jsou deklarovány v bloku bez klíčových slov:
class Foo {
{
// Initialization
}
}
Protože Java má mechanismus shromažďování odpadků, neexistují žádné destruktory . Každý objekt má však finalize()metodu volanou před uvolněním paměti, kterou lze přepsat, aby se implementovala finalizace.
Metody
Všechny příkazy v Javě musí být umístěny v rámci metod. Metody jsou podobné funkcím, kromě toho, že patří do tříd. Metoda má návratovou hodnotu, název a obvykle některé parametry inicializované, když je volána s některými argumenty. Podobně jako v C ++ mají metody vracející nic návratový typ deklarovaný jako void. Na rozdíl od C ++ metody v Javě nesmějí mít výchozí hodnoty argumentů a metody jsou místo toho obvykle přetíženy.
class Foo {
int bar(int a, int b) {
return (a*2) + b;
}
/* Overloaded method with the same name but different set of arguments */
int bar(int a) {
return a*2;
}
}
Metoda se nazývá pomocí .zápisu na objektu nebo v případě statické metody také na názvu třídy.
Foo foo = new Foo();
int result = foo.bar(7, 2); // Non-static method is called on foo
int finalResult = Math.abs(result); // Static method call
throwsKlíčové slovo označuje, že metoda způsobí výjimku. Všechny zaškrtnuté výjimky musí být uvedeny v seznamu odděleném čárkami.
void openStream() throws IOException, myException { // Indicates that IOException may be thrown
}
Modifikátory
-
abstract- Abstraktní metody mohou být přítomny pouze v abstraktních třídách , takové metody nemají tělo a musí být přepsány v podtřídě, pokud nejsou abstraktní samy o sobě. -
static- Nastaví metodu jako statickou a přístupnou bez vytvoření instance třídy. Statické metody však nemohou přistupovat k nestatickým členům ve stejné třídě. -
final- Deklaruje, že metodu nelze v podtřídě přepsat. -
native- Označuje, že tato metoda je implementována prostřednictvím JNI v kódu závislém na platformě. Skutečná implementace se děje mimo kód Java a takové metody nemají tělo. -
strictfp- Deklaruje přísnou shodu s IEEE 754 při provádění operací s plovoucí desetinnou čárkou. -
synchronized- Deklaruje, že vlákno provádějící tuto metodu musí získat monitor. Usynchronizedmetod je monitor instancí třídy nebojava.lang.Classpokud je metoda statická. - Modifikátory přístupu - shodné s těmi, které se používají s třídami.
Varargs
Tato jazyková funkce byla představena v J2SE 5.0 . Poslední argument metody může být deklarován jako parametr proměnné arity, v takovém případě se metoda stane metodou proměnné arity (na rozdíl od metod pevné arity) nebo jednoduše metodou varargs . To umožňuje předat metodě proměnný počet hodnot deklarovaného typu jako parametry - včetně žádných parametrů. Tyto hodnoty budou k dispozici uvnitř metody jako pole.
void printReport(String header, int... numbers) { //numbers represents varargs
System.out.println(header);
for (int num : numbers) {
System.out.println(num);
}
}
// Calling varargs method
printReport("Report data", 74, 83, 25, 96);
Pole
Pole nebo proměnné třídy lze deklarovat v těle třídy pro ukládání dat.
class Foo {
double bar;
}
Pole lze inicializovat přímo při deklaraci.
class Foo {
double bar = 2.3;
}
Modifikátory
-
static- Učiní z pole statický prvek. -
final- Umožňuje inicializaci pole pouze jednou v konstruktoru nebo uvnitř inicializačního bloku nebo během jeho deklarace, podle toho, co nastane dříve. -
transient- Udává, že toto pole nebude během serializace uloženo . -
volatile- Pokud je pole deklarovánovolatile, je zajištěno, že všechna vlákna uvidí pro proměnnou konzistentní hodnotu.
Dědictví
Třídy v Javě mohou dědit pouze z jedné třídy. Třídu lze odvodit z jakékoli třídy, která není označena jako final. Dědičnost je deklarována pomocí extendsklíčového slova. Třída se může odkazovat sama pomocí thisklíčového slova a jeho přímá nadtřída pomocí superklíčového slova.
class Foo {
}
class Foobar extends Foo {
}
Pokud třída neurčí svou nadtřídu, implicitně dědí ze java.lang.Objecttřídy. Všechny třídy v Javě jsou tedy podtřídy Objecttřídy.
Pokud nadtřída nemá konstruktor bez parametrů, podtřída musí ve svých konstruktérech určit, jaký konstruktor nadtřídy použít. Například:
class Foo {
public Foo(int n) {
// Do something with n
}
}
class Foobar extends Foo {
private int number;
// Superclass does not have constructor without parameters
// so we have to specify what constructor of our superclass to use and how
public Foobar(int number) {
super(number);
this.number = number;
}
}
Převažující metody
Na rozdíl od C ++ jsou všechny ne- finalmetody v Javě virtuální a mohou být přepsány dědícími třídami.
class Operation {
public int doSomething() {
return 0;
}
}
class NewOperation extends Operation {
@Override
public int doSomething() {
return 1;
}
}
Abstraktní třídy
Abstract Class je třída, která je neúplná, nebo mají být považována za neúplnou. Normální třídy mohou mít abstraktní metody, tj. Metody, které jsou deklarovány, ale ještě nejsou implementovány, pouze pokud jsou abstraktní třídy. Třída C má abstraktní metody, pokud platí některá z následujících:
- C výslovně obsahuje deklaraci abstraktní metody.
- Kterákoli ze superclassů C má abstraktní metodu a C nedeklaruje ani nedědí metodu, která ji implementuje.
- Přímé superinterface C deklaruje nebo dědí metodu (která je tedy nutně abstraktní) a C ani nedeklaruje, ani nedědí metodu, která ji implementuje.
- Lze vytvořit instanci podtřídy abstraktní třídy, která sama o sobě není abstraktní, což má za následek spuštění konstruktoru pro abstraktní třídu, a tedy provedení inicializátorů pole pro proměnné instance této třídy.
package org.dwwwp.test;
/**
* @author jcrypto
*/
public class AbstractClass {
private static final String hello;
static {
System.out.println(AbstractClass.class.getName() + ": static block runtime");
hello = "hello from " + AbstractClass.class.getName();
}
{
System.out.println(AbstractClass.class.getName() + ": instance block runtime");
}
public AbstractClass() {
System.out.println(AbstractClass.class.getName() + ": constructor runtime");
}
public static void hello() {
System.out.println(hello);
}
}
package org.dwwwp.test;
/**
* @author jcrypto
*/
public class CustomClass extends AbstractClass {
static {
System.out.println(CustomClass.class.getName() + ": static block runtime");
}
{
System.out.println(CustomClass.class.getName() + ": instance block runtime");
}
public CustomClass() {
System.out.println(CustomClass.class.getName() + ": constructor runtime");
}
public static void main(String[] args) {
CustomClass nc = new CustomClass();
hello();
//AbstractClass.hello();//also valid
}
}
Výstup:
org.dwwwp.test.AbstractClass: static block runtime
org.dwwwp.test.CustomClass: static block runtime
org.dwwwp.test.AbstractClass: instance block runtime
org.dwwwp.test.AbstractClass: constructor runtime
org.dwwwp.test.CustomClass: instance block runtime
org.dwwwp.test.CustomClass: constructor runtime
hello from org.dwwwp.test.AbstractClass
Výčty
Tato jazyková funkce byla představena v J2SE 5.0 . Technicky výčty jsou jakousi třídou obsahující ve svém těle konstanty výčtu. Každá konstanta výčtu definuje instanci typu výčet. Třídy výčtu nelze vytvořit instanci kdekoli kromě samotné třídy výčtu.
enum Season {
WINTER, SPRING, SUMMER, AUTUMN
}
Konstanty výčtu mohou mít konstruktory, které jsou volány při načtení třídy:
public enum Season {
WINTER("Cold"), SPRING("Warmer"), SUMMER("Hot"), AUTUMN("Cooler");
Season(String description) {
this.description = description;
}
private final String description;
public String getDescription() {
return description;
}
}
Výčty mohou mít těla tříd, v takovém případě jsou považovány za anonymní třídy rozšiřující třídu výčtu:
public enum Season {
WINTER {
String getDescription() {return "cold";}
},
SPRING {
String getDescription() {return "warmer";}
},
SUMMER {
String getDescription() {return "hot";}
},
FALL {
String getDescription() {return "cooler";}
};
}
Rozhraní
Rozhraní jsou typy, které neobsahují žádná pole a obvykle definují řadu metod bez skutečné implementace. Jsou užitečné k definování smlouvy s libovolným počtem různých implementací. Každé rozhraní je implicitně abstraktní. Metody rozhraní mohou mít podmnožinu modifikátorů přístupu v závislosti na jazykové verzi strictfp, která má stejný účinek jako pro třídy, a také staticod Java SE 8.
interface ActionListener {
int ACTION_ADD = 0;
int ACTION_REMOVE = 1;
void actionSelected(int action);
}
Implementace rozhraní
Rozhraní je implementováno třídou pomocí implementsklíčového slova. Je povoleno implementovat více než jedno rozhraní, v takovém případě jsou zapsány za implementsklíčové slovo v seznamu odděleném čárkami. Třída implementující rozhraní musí přepsat všechny své metody, jinak musí být deklarována jako abstraktní.
interface RequestListener {
int requestReceived();
}
class ActionHandler implements ActionListener, RequestListener {
public void actionSelected(int action) {
}
public int requestReceived() {
}
}
//Calling method defined by interface
RequestListener listener = new ActionHandler(); /*ActionHandler can be
represented as RequestListener...*/
listener.requestReceived(); /*...and thus is known to implement
requestReceived() method*/
Funkční rozhraní a výrazy lambda
Tyto funkce byly zavedeny s vydáním Java SE 8. Rozhraní se automaticky stane funkčním rozhraním, pokud definuje pouze jednu metodu. V tomto případě může být implementace reprezentována jako výraz lambda namísto implementace v nové třídě, což výrazně zjednodušuje psaní kódu ve funkčním stylu . Funkční rozhraní lze volitelně anotovat @FunctionalInterfaceanotací, která kompilátoru řekne, aby zkontroloval, zda rozhraní skutečně odpovídá definici funkčního rozhraní.
// A functional interface
@FunctionalInterface
interface Calculation {
int calculate(int someNumber, int someOtherNumber);
}
// A method which accepts this interface as a parameter
int runCalculation(Calculation calculation) {
return calculation.calculate(1, 2);
}
// Using a lambda to call the method
runCalculation((number, otherNumber) -> number + otherNumber);
// Equivalent code which uses an anonymous class instead
runCalculation(new Calculation() {
@Override
public int calculate(int someNumber, int someOtherNumber) {
return someNumber + someOtherNumber;
}
})
Typy parametrů Lambda nemusí být plně specifikovány a lze je odvodit z rozhraní, které implementuje. Tělo Lambdy lze zapsat bez bloku těla a returnpříkazu, pokud jde pouze o výraz. Také pro ta rozhraní, která mají v metodě pouze jeden parametr, lze vynechat kulaté závorky.
// Same call as above, but with fully specified types and a body block
runCalculation((int number, int otherNumber) -> {
return number + otherNumber;
});
// A functional interface with a method which has only a single parameter
interface StringExtender {
String extendString(String input);
}
// Initializing a variable of this type by using a lambda
StringExtender extender = input -> input + " Extended";
Odkazy na metody
Pokud již existuje pojmenovaná metoda kompatibilní s rozhraním, není nutné používat lambdas. Tuto metodu lze předat místo lambda pomocí odkazu na metodu. Existuje několik typů odkazů na metody:
| Typ odkazu | Příklad | Ekvivalentní lambda |
|---|---|---|
| Statický | Integer::sum |
(number, otherNumber) -> number + otherNumber
|
| Vázaný | "LongString"::substring |
index -> "LongString".substring(index)
|
| bez závazků | String::isEmpty |
string -> string.isEmpty()
|
| Konstruktor třídy | ArrayList<String>::new |
capacity -> new ArrayList<String>(capacity)
|
| Pole konstruktor | String[]::new |
size -> new String[size]
|
Kód, nad kterým lze volání runCalculationnahradit pomocí odkazů na metody, je následující:
runCalculation(Integer::sum);
Dědictví
Rozhraní mohou dědit z jiných rozhraní stejně jako třídy. Na rozdíl od tříd je povoleno dědění z více rozhraní. Je však možné, že několik rozhraní má pole se stejným názvem, v takovém případě se stane jediným nejednoznačným členem, ke kterému není přístup.
/* Class implementing this interface must implement methods of both
ActionListener and RequestListener */
interface EventListener extends ActionListener, RequestListener {
}
Výchozí metody
Java SE 8 zavedla do rozhraní výchozí metody, které vývojářům umožňují přidávat nové metody do stávajících rozhraní, aniž by byla narušena kompatibilita s třídami, které již rozhraní implementují. Na rozdíl od běžných metod rozhraní mají výchozí metody tělo, které se zavolá v případě, že jej implementační třída nepřepíše.
interface StringManipulator {
String extendString(String input);
// A method which is optional to implement
default String shortenString(String input) {
return input.substring(1);
}
}
// This is a valid class despite not implementing all the methods
class PartialStringManipulator implements StringManipulator {
@Override
public String extendString(String input) {
return input + " Extended";
}
}
Statické metody
Statické metody jsou další jazykovou funkcí zavedenou v Java SE 8. Chovají se úplně stejně jako ve třídách.
interface StringUtils {
static String shortenByOneSymbol(String input) {
return input.substring(1);
}
}
StringUtils.shortenByOneSymbol("Test");
Soukromé metody
Ve verzi Java 9 byly přidány soukromé metody. Rozhraní může mít metodu s tělem označeným jako soukromá, v takovém případě nebude viditelná pro dědění tříd. Lze jej volat z výchozích metod pro účely opětovného použití kódu.
interface Logger {
default void logError() {
log(Level.ERROR);
}
default void logInfo() {
log(Level.INFO);
}
private void log(Level level) {
SystemLogger.log(level.id);
}
}
Anotace
Anotace v Javě představují způsob, jak vložit metadata do kódu. Tato jazyková funkce byla představena v J2SE 5.0 .
Typy anotací
Java má sadu předdefinovaných typů anotací, ale je povoleno definovat nové. Deklarace typu anotace je speciální typ deklarace rozhraní. Jsou deklarovány stejným způsobem jako rozhraní, kromě toho, že interfaceklíčovému slovu předchází @znak. Všechny anotace jsou implicitně rozšířeny z java.lang.annotation.Annotationa nelze je rozšířit z ničeho jiného.
@interface BlockingOperations {
}
Anotace mohou mít v těle stejná prohlášení jako běžná rozhraní, navíc mohou obsahovat výčty a anotace. Hlavní rozdíl je v tom, že deklarace abstraktní metody nesmí mít žádné parametry ani vyvolávat žádné výjimky. Také mohou mít výchozí hodnotu, která je deklarována pomocí defaultklíčového slova za názvem metody:
@interface BlockingOperations {
boolean fileSystemOperations();
boolean networkOperations() default false;
}
Použití anotací
Anotace lze použít v jakémkoli druhu deklarace, ať už jde o balíček, třídu (včetně výčtů), rozhraní (včetně anotací), pole, metodu, parametr, konstruktor nebo lokální proměnnou. Mohou být také použity s konstantami výčtu. Anotace jsou deklarovány pomocí @znaku předcházejícího názvu typu anotace, po kterém jsou páry prvků a hodnot zapsány do závorek. Všem prvkům bez výchozí hodnoty musí být přiřazena hodnota.
@BlockingOperations(/*mandatory*/ fileSystemOperations,
/*optional*/ networkOperations = true)
void openOutputStream() { //Annotated method
}
Kromě generické formy existují ještě dvě další formy pro deklaraci anotace, což jsou zkratky. Anotace značek je krátká forma, používá se, když nejsou k prvkům přiřazeny žádné hodnoty:
@Unused // Shorthand for @Unused()
void travelToJupiter() {
}
Druhá krátká forma se nazývá anotace jednoho prvku . Používá se u typů anotací obsahujících pouze jeden prvek nebo v případě, že je přítomno více prvků, ale pouze u jednoho prvku chybí výchozí hodnota. V anotaci jednoho prvku je název prvku vynechán a místo toho je zapsána pouze hodnota:
/* Equivalent for @BlockingOperations(fileSystemOperations = true).
networkOperations has a default value and
does not have to be assigned a value */
@BlockingOperations(true)
void openOutputStream() {
}
Generika
Generika nebo parametrizované typy nebo parametrický polymorfismus je jednou z hlavních funkcí představených v J2SE 5.0 . Před zavedením generik bylo nutné explicitně deklarovat všechny typy. S generiky bylo možné pracovat podobným způsobem s různými typy bez deklarování přesných typů. Hlavním účelem generik je zajistit bezpečnost typů a detekovat chyby za běhu během kompilace. Na rozdíl od C#nejsou informace o použitých parametrech za běhu k dispozici kvůli vymazání typu .
Obecné třídy
Třídy lze parametrizovat přidáním proměnné typu do hranatých závorek ( <a >) za název třídy. Umožňuje použití této proměnné typu u členů třídy namísto skutečných typů. Může existovat více než jedna typová proměnná, v takovém případě jsou deklarovány v seznamu odděleném čárkami.
Je možné omezit proměnnou typu na podtyp nějaké konkrétní třídy nebo deklarovat rozhraní, které musí typ implementovat. V tomto případě je k proměnné typu připojeno extendsklíčové slovo, za nímž následuje název třídy nebo rozhraní. Pokud je proměnná omezena jak třídou, tak rozhraním nebo pokud existuje několik rozhraní, nejprve se zapíše název třídy a poté názvy rozhraní se & znakem použitým jako oddělovač.
/* This class has two type variables, T and V. T must be
a subtype of ArrayList and implement Formattable interface */
public class Mapper<T extends ArrayList & Formattable, V> {
public void add(T array, V item) {
// array has add method because it is an ArrayList subclass
array.add(item);
}
}
Když je deklarována proměnná parametrizovaného typu nebo je vytvořena instance, její typ je zapsán přesně ve stejném formátu jako v záhlaví třídy, kromě toho, že skutečný typ je zapsán na místo deklarace proměnné typu.
/* Mapper is created with CustomList as T and Integer as V.
CustomList must be a subclass of ArrayList and implement Formattable */
Mapper<CustomList, Integer> mapper = new Mapper<CustomList, Integer>();
Od Java SE 7 je možné <>místo argumentů typu použít diamond ( ), v takovém případě bude odvozeno druhé. Následující kód v jazyce Java SE 7 je ekvivalentní kódu v předchozím příkladu:
Mapper<CustomList, Integer> mapper = new Mapper<>();
Při deklarování proměnné pro parametrizovaný typ je možné místo explicitních názvů typů použít zástupné znaky. Zástupné znaky jsou vyjádřeny znakem psaní ?místo skutečného typu. Je možné omezit možné typy na podtřídy nebo nadtřídy určité konkrétní třídy zapsáním extendsklíčového slova nebo superklíčového slova odpovídajícím způsobem za názvem třídy.
/* Any Mapper instance with CustomList as the first parameter
may be used regardless of the second one.*/
Mapper<CustomList, ?> mapper;
mapper = new Mapper<CustomList, Boolean>();
mapper = new Mapper<CustomList, Integer>();
/* Will not accept types that use anything but
a subclass of Number as the second parameter */
void addMapper(Mapper<?, ? extends Number> mapper) {
}
Obecné metody a konstruktory
Použití generik může být omezeno na některé konkrétní metody, tento koncept platí i pro konstruktéry. K deklarování parametrizované metody se typové proměnné zapisují před návratový typ metody ve stejném formátu jako pro obecné třídy. V případě konstruktoru jsou proměnné typu deklarovány před názvem konstruktoru.
class Mapper {
// The class itself is not generic, the constructor is
<T, V> Mapper(T array, V item) {
}
}
/* This method will accept only arrays of the same type as
the searched item type or its subtype*/
static <T, V extends T> boolean contains(T item, V[] arr) {
for (T currentItem : arr) {
if (item.equals(currentItem)) {
return true;
}
}
return false;
}
Obecná rozhraní
Rozhraní lze parametrizovat podobným způsobem jako třídy.
interface Expandable<T extends Number> {
void addItem(T item);
}
// This class is parameterized
class Array<T extends Number> implements Expandable<T> {
void addItem(T item) {
}
}
// And this is not and uses an explicit type instead
class IntegerArray implements Expandable<Integer> {
void addItem(Integer item) {
}
}
Viz také
Reference
- Patrick Naughton , Herbert Schildt . Java 2: The Complete Reference , třetí vydání. Společnosti McGraw-Hill, 1999. ISBN 0-07-211976-4
- Vermeulen; Mimochod; Bumgardner; Metz; Misfeldt; Shur; Thompson (2000). The Elements of Java Style . Cambridge University Press. ISBN 0-521-77768-2.
- Gosling, James ; Radost, Bille ; Steele, Guy ; Bracha, Gillad (2005). Specifikace jazyka Java (3. vydání). Addison-Wesley Professional . Citováno 2008-12-03 .
externí odkazy
- Specifikace jazyka Java, třetí vydání Autoritativní popis jazyka Java
- Java SE 10 API Javadocs