1. seminář - Základní konstrukce

TEACHINGJJ1

Jazyk Java

  • Objektově orientovaný jazyk
  • Syntaxe vychází z C/C++
  • Na rozdíl od C/C++ máme:
    • Automatická správa paměti
    • Kontrola mezí polí
    • Pouze bezpečné prvky jazyka
    • Jiný objektový systém
  • Portabilita (Přenostitelnost)
  • Systém výjimek
  • Více implementací (Oracle, OpenJDK, …)
  • Bohatá standardní knihovna a mnoho dalších knihoven
  • Nová verze dvakrát ročně (od Java 10)

Platforma Java

  • Sada mnoha nástrojů umožňující vývoj (nejen) v Javě
  • Dostupné pro různorodý hardware (portabilita)
  • JVM - Java Virtual Machine
  • JDK - Java Development Kit
  • JRE - Java Runtime Environment
  • Podporuje mnoho dalších jazyků: Scala, Groovy, Clojure, Kotlin, …
  • JavaCard (applety), Java ME (malá zařízení), Java SE, Jakarta EE (podnikové systémy)

IDE (Integrated development environment)

IDE nabízí spoustu možností, jak si usnadnit práci. Využívejte toho!

  • Formátování
  • Generování kódu
  • Refactoring
  • Debugger
  • Profiler
  • Naštěpávač
  • Rady
  • Verzování
  • Pluginy

Základní konstrukce jazyka Java

V této kapitole jsou popsány základní konstrukce Jazyka Java, které je nutné bezpodmínečně znát.

Konvence

Veškerý odevzdaný kód musí dodržovat konvence, jinak bude vrácen k přepracování. Budeme používat Google konvence.

Čitelnost kódu je velmi důležitá vlastnost.

Příkazy a bloky

Příkazy ukončujeme středníkem, např.


    System.out.println("Hello World!");

Výše uvedený příkaz vypíše na obrazovku Hello World!

Bloky jsou uzavřeny do složených závorek, např.


    {
        System.out.println("Hello World!");
        System.out.println("How are you?");
        System.out.println("BUM!");
    }

Primitivní datové typy

  • boolean
    • pravdivostní hodnoty
    • literály true a false
  • char
    • znaky (unicode)
    • literály v ''
    • escape sequence začínaji \, např. '\n','\t', '\\', …
    • unicode znaky \uXXXX, kde X je šestnáctková číslice
  • byte
    • celá čísla od -128 do 127 (27)
    • nemá literály (přetypování)
  • short
    • celá čísla od -32 768 do 32 767 (215)
    • nemá literály (přetypování)
  • int
    • celá čísla od -2 147 483 648 do 2 147 483 647 (231)
    • více možnýh soustav (Y je libovolná číslice dané soustavy):
      • dvojková - tvar 0bYYY...
      • osmičková - tvar 0YYY...
      • desítková - klasika, nesmí začínat 0
      • šestnáctková - tvar 0xYYYY
    • literály jsou prostě celá čísla v daném rozsahu
  • long
    • celá čísla od -9 223 372 036 854 775 808 do 9 223 372 036 854 775 807 (263)
    • literály končí znakem L, např 123L
  • float
    • reálná čísla s přesností na 6 číslic
    • literály končí znakem F, např 0.25F
  • double
    • reálná čísla s přesností na 15 číslic
    • literály:
      • prostě desetinná čísla v daném rozsahu
      • celé číslo končící znakem D, např 123D
      • číslo v exponentovém/vědeckém tvaru, např 3.14159e5 pro 3.14159 ⋅ 105
    • navíc NaN, POSITIVE_INFINITY, NEGATIVE_INFINITY

Přetypování

  • Implicitně ze specifičtějšího typu na obecnější, tj např lze uložit int do double proměnné nebo char do int proměnné. Naopak implicitně nelze.

  • Explicitně když víme něco víc než překladač.

    • Syntaxe: (novyTyp) hodnota.

    • Např

      int a = (int) funkceBezneVracejiciDouble(arg1, arg2)

      když vím, že zronva s těmito argumenty moje funkce vrátí celé číslo.

    • Typické použítí je přesné dělení dvou celých čísel operátorem / (viz dále) nebo useknutí desetinné části z double hodnoty (pozor na velikost).

    • Literály i práce s typy byte a short vyžadují přetypování, neboť např (byte) a + (byte) b je typu int. Chceme-li zase byte, pak musíme použít

      (byte)((byte) a + (byte) b)

Operátory

Priorita odshora dolů.

A je-li zle tak: “Když nevíš, dej tam závorky.” Tj (skoro) vše se dá uzávorkovat tak, aby člověk určil, v jakém pořadí se mají části výrazu vyhodnocovat.

Unární

Postfixové

  • ++
  • --

Prefixové

  • ++
  • --
  • +
  • -
  • ! - negace
  • ~ - bitový doplňěk

Binární

Multiplikativní

  • *
  • /
  • % - zbytek po celočísleném dělení

Aditivní

  • +
  • -

Posun

  • << - bitový posun doleva (vyplňuje 0)
  • >> - bitový posun doprava (vyplňuje znaménkovým bitem)
  • >>> - bitový posun doprava (vyplňuje 0)

Relační

  • <
  • >
  • <=
  • >=
  • instanceof

Relační - (ne)rovnost

  • ==
  • !=

Bitové

  • & - bitové AND
  • ^ - bitové XOR
  • | - bitové OR

Logické

  • &&
  • ||

Ternární

  • ? :

Přiřazení

  • =
  • +=
  • -=
  • *=
  • /=
  • %=
  • &=
  • ^=
  • |=
  • <<=
  • >>=
  • >>>=

O něco úplnější tabulka s operátory v Javě.

Proměnné

Jazyk Java je staticky typovaný programovací jazyk. Od verze 10 umožňuje použít tzv. typovou inferenci (odvození typu).


    var secretNumber = 10;

nebo


    var secretPassword = "topS3cr3t";

Ale pozor, nemůžeme napsat:


    var x;

V tomto případě interpret nemá z čeho odvodit typ a volání skončí chybou.

Obecně se proměnné deklarují ve tvaru


    // Deklarace proměnné
    type variableName;
    
    // Deklarace proměnné s výchozí hodnotou
    type variableName = default_value;

Příklady deklarací


    int number = 123;
    double doubleNumber = 2.88;
    String greeting = "Hello"; 

Konstanty

Při programovaná se stává že hodnotu potřebujeme nastavit pouze 1 a pak zněmožnit její přepsání. Toho docílíme pomocí klíčového slova final.


    final double PI = 3.14;

Podmíněný příkaz

Podmíněné příkazy vypadají podobně jako v C:


    if (condition) {
        statements;
    }
    
    if (condition) {
        statements;
    } else {
        statements;
    }
    
    if (condition) {
        statements;
    } else if (condition) {
        statements;
    } else {
        statements;
    }

V javě stejně jako v C máme k dispozici i ternární operátor:


    x = (y == 27) ? 10 : 20;

Switch

V Javě lze od verze 16 switch použít jako příkaz i jako výraz a od verze 17 možnost pattern matchingu ve switch příkazech/výrazech.

Switch jako příkaz


    switch (condition) {
       case option:
          statements;
          /* falls through */
       case 1:
          statements;
          break;
       case 2:
          statements;
          break;
       default:
          statements;
          break;
    }

Switch jako výraz


    switch (condition) {
       case label_1, label_2, label_3 -> value_1;
       .
       .
       .
       case label_n                    -> value_m;
       default -> default_value;
    }
    
    // Příklad
    var monthNumber = 2;
    
    var numberOfDays = switch(month) {
        case 1, 3, 5, 7, 8, 10, 12 -> 31;
        case 2 -> 28;
        case 4, 6, 9, 11 -> 30;
        default -> 0; 
    };


Switch pomoci yield


    switch (condition) {
       case label_1:
       case label_2:
       case label_3:
          statements;
          yield value_1;
       .
       .
       .
       case label_n:
          statements;
          yield value_m;
       default:
          statements;
          yield default_value;
    }
    
    // Příklad
    var numberOfDays = switch(month) {
        case 1, 3, 5, 7, 8, 10, 12 -> 31 {
            S
        case 2 -> 28;
        case 4, 6, 9, 11 -> 30;
        default -> 0; 
    };

Switch výrazy musí být vyčerpávající, tedy jednotlivé větve musí zahrnout každý možný případ. Lze vyřešit default větví. U switch přes malé enumy (výčtové typy, uvidíme později) lze vypsat všechny možnosti a default vynechat - kompilátor si jej doplní. Navíc ze switch výrazů nelze utéct pomocí break; či continue;, protože musí vrátit hodnotu.

Pro switch příkazy tato omezení neplatí.

Cykly

U všech cyklů fungují příkazy break; a continue;. Příkaz break; cyklus ukončí, continue; přejde k další iteraci.

For cyklus


    for (initialization; condition; update) {
       statements;
    }

While cyklus


    while (condition) {
       statements;
    }

Do-while cyklus


    do {
       statements;
    } while (condition);

Metody (funkce)


    return-type name (type1 arg1, type2 arg2, ..., typen argn) {
      statements;
      return return-value;
    }

Pokud metoda nemá nic vracet, její návratový typ return-type je void (bude se hodit v úkolech níže).

Úkoly

Úkoly mi neposílejte, budou zkontrolovány na dalším semináři.

Napište funkci primes beroucí jeden argument typu int, která vypíše všechna prvočísla menší než zadaný argument oddělená čárkou a mezerou (ve standardním pořadí). Za posledním vypsaným číslem bude taktéž čárka a mezera.

    static void primes(int upperBound) {
        // Vase reseni
    }
       
Napište funkci multiply ob beroucí dva argumenty typu int vracející jejich součin, ale používající z aritmetických operací pouze sčítání a odčítání. Mohou se hodit funkce z knihovny Math (vizte dokumentaci).

    static int multiply(int left, int right) {
        // Vase reseni
    }
    
    multiply(5, 6); // -> 30 
       
Napište funkci nameNumber vracející pro zadané číslo v rozsahu 1 až 10 jemu odpovídající české slovo a pro čísla mimo zadaný rozsah vrátí slovo “neznám”.

    nameNumber(3); // -> "Tři" 
       
Napište funkci printTriangle která bere délku strany rovnostranného trojúhelníku a vytiskne jej na obrazovku následovně:

    // n = 5
    
        *
       ** 
      * * 
     *  *    
    *****