Obsah

Pole

Vincent van Gogh: Wheat field (Národní galerie v Praze)

Pole umožňuje elegantně pracovat s více hodnotami stejného typu. Pro uložení např. deseti hodnot typu int můžeme buď zavést deset proměnných nebo vytvořit pole o deseti prvcích. V mnoha případech se s polem pracuje snadněji. Typ pole zapisujeme v Javě pomocí hranatých závorek. Deklarace proměnné typu pole položek typu int vypadá takto:

  int[] p; 
Proměnná typu pole je tzv. reference. Bude obsahovat odkaz (referenci) na pole. Samotná deklarace pole nevytváří. Pole můžeme vytvořit pomocí klíčového slova new:
  p = new int[4]; 
V tomto případě jsme vytvořili pole o čtyřech prvcích typu int. Počet prvků pole je v proměnné length daného pole. Hodnota této proměnné je nastavena při vytvoření pole a nelze ji změnit (je pouze pro čtení).
  System.out.printf( "pole p má %d prvků%n", p.length ); 
K jednotlivým prvkům pole přistupujeme pomocí indexů, které zapisujeme do hranatých závorek: pole
  p[1] = 5; 
Indexy začínají vždy od nuly, tj. platné indexy jsou z intervalu <0, length-1>. Pro pole p tedy 0, 1, 2 a 3. Platnost indexu se kontroluje za běhu programu. Použití neplatného indexu způsobí běhovou chybu. Po vytvoření jsou prvky pole inicializovány na hodnoty, jejichž vnitřní reprezentace je 0. U číselných typů je to 0, u typu boolean je to false a u typu char je to znak na pozici 0 v tabulce Unicode. Pro načtení hodnot do pole používáme obvykle cyklus for:
  Scanner sc = new Scanner( System.in );
  int[] p = new int[10];
  for( int i = 0; i < p.length; i++ ) {
     p[i] = sc.nextInt();
  } 
Výpis pole provedeme opět cyklem for:
  for( int i = 0; i < p.length; i++ ) {
     System.out.println( p[i] );
  } 
Délka pole musí být nezáporná. Pokus vytvořit pole záporné délky způsobí chybu. Vytvoření pole lze spojit s inicializací. V takovém případě se nepoužívá new:
  int[] prvocisla = { 2, 3, 5, 7, 11, 13, 17, 19 }; 
Velikost pole je dána počtem hodnot ve složených závorkách. Pole může být parametrem metody:
  static int sectiPole( int[] cisla ) {
     int soucet = 0;
     for( int i = 0; i < cisla.length; i++ ) {
        soucet += cisla[i];
     }
     return soucet;
  } 
Může být i návratovým typem: metoda zduplikujPole
  static int[] zduplikujPole( int[] p ) {
     int[] nove = new int[p.length * 2];
     for( int i = 0; i < p.length; i++ ) {
        nove[i] = nove[i + p.length] = p[i];
     }
     return nove;
  } 
Metoda zduplikujPole nejprve vytvoří pole o dvojnásobném počtu prvků než má pole p a pak pole p dvakrát za sebou překopíruje do nově vytvořeného pole. Návratovou hodnotou metody je nově vytvořené pole.

Velikost vytvářeného pole nemusí být konstantní výraz, tj. nemusí být známa při překladu. Můžeme vytvořit pole, jehož počet prvků je dán např. hodnotou proměnné.

  Scanner sc = new Scanner( System.in );
  int n = sc.nextInt();
  double[] p = new double[n]; // velikost pole je dána proměnnou n 
Proměnná typu pole obsahuje odkaz (referenci) na pole. Každá reference zabírá v JVM 32 bitů. Do proměnné typu pole lze přiřadit hodnotu jiné proměnné stejného typu. Při přiřazení dojde ke zkopírování hodnoty reference. reference na pole Při předávání pole do metody se předává hodnota reference. Nedochází tedy k žádnému kopírování pole. To umožňuje v metodě měnit hodnoty prvků pole předaného jako parametr.
  // prohodí první a poslední prvek v poli
  static void prohod( int[] p ) {
     int n = p.length – 1, pp = p[0];
     p[0] = p[n];
     p[n] = pp;
  } 
Při volání je do proměnné p zkopírována hodnota skutečného parametru.
  int[] cisla = { 1, 2, 3 };
  prohod( cisla );
  // pole cisla obsahuje hodnoty 3, 2, 1
  System.out.printf( "%d, %d, %d%n", cisla[0], cisla[1], cisla[2] ); 
Hodnotu skutečného parametru ve volané metodě změnit nelze. Lze měnit pouze hodnoty v poli, na které skutečný parametr odkazuje.
  // tato metoda nemá žádný efekt, protože p je lokální proměnná
  static void metodaNula( int[] p ) {
     p = new int[2];
     p[0] = 10;
     p[1] = 20;
  } 
Po provedení metody metodaNula bude hodnota skutečného parametru stejná jako před voláním.
  int[] cisla = { 1, 2, 3 };
  metodaNula( cisla );
  // pole cisla obsahuje hodnoty 1, 2, 3
  System.out.printf( "%d, %d, %d%n", cisla[0], cisla[1], cisla[2] ); 

Úloha 1

Doplňte vytvoření pole c tak, aby po provedení cyklu obsahovalo všechny znaky anglické abecedy.

Úloha 2

Doplňte tělo metody, jež nastaví prvky v poli h na hodnotu v.

Úloha 3

Doplňte tělo metody, která obrátí pořadí prvků v poli.

Úloha 4

Doplňte tělo metody obsahuje. Metoda vrací true pokud pole p obsahuje hodnotu h, jinak vrací false.

Úloha 5

Doplňte tělo metody, která sečte dva vektory typu double. Vektory nemusí mít stejný počet prvků.

Úloha 6

Napište ve správném pořadí.

Úloha 7

Rozhodněte, zda je tvrzení pravdivé.

Otázky a odpovědi

Studentka: Mistře, pokud mám počet prvků pole v proměnné, můžu tuto proměnou používat namísto proměnné length? Např. v následujícím kódu je počet prvků pole v proměnné n:
  Scanner sc = new Scanner( System.in );
  int n = sc.nextInt();
  double[] h = new double[n]; 
Můžu proměnnou n použít v cyklu pro práci s polem? Např. takto:
  for( int i = 0; i < n; i++ ) {
     //...
  } 
Java guru: Můžeš, takto zapsaný cyklus je správně. Použití proměnné length je však většinou lepší. Představ si, že se po napsání tohoto kódu rozhodneš změnit délku pole z n na n+1.
  Scanner sc = new Scanner( System.in );
  int n = sc.nextInt();
  double[] h = new double[n + 1];  // n změníme na n+1
  for( int i = 0; i < h.length; i++ ) {
     h[i] = sc.nextInt();
  } 
Pokud jsi dále v kódu používala důsledně proměnnou length, stačí změnit délku pole na jednom místě – při vytváření. Pokud jsi ovšem používala n jako počet prvků pole, bude potřeba každý výskyt n nahradit výrazem n+1.
Studentka: Mistře, patří new mezi operátory?
Java guru: Nepatří. V některých učebnicích jej mezi operátory počítají, není to však zcela správně. V Javě to operátor není. Nicméně rozdíl mezi tím, zda to operátor je či není, je víceméně formální. Takže si z toho nemusíš dělat těžkou hlavu.