Deprecated: Function set_magic_quotes_runtime() is deprecated in /DISK2/WWW/lokiware.info/mff/wakka.php on line 35 Matfiz : Java

Matfiz: Java

Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256 Deprecated: Function split() is deprecated in /DISK2/WWW/lokiware.info/mff/formatters/classes/WackoFormatter.php on line 256

Java

Přednášející: Petr Hnětynka (Na jeho webu najdete slajdy, požadavky k zápočtu apod.)

Zápočet

K zápočtu je třeba docházka a/nebo úkoly, zápočtový program (projekt) a praktický zápočtový test v labu (podrobnosti na Hnětynkových stránkách). Za zmínku stojí, že s sebou můžete mít jakékoli psané a tištěné materiály, ale na webu můžete jen na dokumentaci JDK a, podle toho co říkal, i když na webu to nemá, slajdy z přednášky.

Možné řešení testu ze 4. 2. 2009 14:00: file:zapoctovadb.javaAdam

Pozorování: Některá zadání jsou výrazně lehčí, a některá výrazně těžší. Na nic nepotřebujete být geniální programátoři ani mít hluboké znalosti API a už vůbec ne objektově orientovaného programování (Mimochodem, všimli jste si, že tohle je společný znak všech zkoušek a zápočtů z objektově orientovaných jazyků a dokonce i předmětu, který se z mě neznámého důvodu jmenuje Objektově orientované programování? Není to podezřelé?), ale některé věci prostě sežerou víc kódu, a tedy i času. Časový limit bývá docela přesně dodržován (tj. prodlužuje se třeba o čtvrt hodiny, ale ne o hodinu). Úspěšnost některých termínu je proto menší než poloviční. Takže pokud to napoprvé prostě nestihnete, nevěšte hlavu, příště (nebo přespříště:/) nejspíš dostanete něco fakt snadného. — Adam

Můžou se Vám hodit tyhle !/Kousky Kódu (když si je vytisknete, na net se totiž mimo dokumentace API nesmí).

Zkouška

Probíhá formou testu (trochu jako C++). Letošní otázky (z 2. 2. 2008) najdete na fóru. Bodování i obtížnost se od minulého roku trochu změnila, viz otázky z minulého roku (leden 2008), najdete na velké matfyzácké wiki.

Řešení psacích otázek z 2. 2. 2008:

Pro řešení zaškrtávacích otázek viz vlákno na fóru.

9. Napište metodu, která má dva parametry typu int, hrubou mzdudaň v procentech, a vrací hodnotu typu double udávající daň k zaplacení. Ověřte, že daň je v rozmezí 0–100 a mzda je nezáporná, pokud parametry nejsou v pořádku vyhoďte výjimku MyException, která je přímým potomkem java.lang.Exception (předpokládá se, že je deklarovaná a importovaná).

Řešení:

public class TaxCalculator{
  /* MyException je přímý potomek java.lang.Exception => je třeba deklarovat: */
  public double calculateTax(int gross, int taxPercentage) throws MyException{
    if( gross < 0 || taxPercentage < 0 || taxPercentage > 100 )
      throw new MyException();
    /* Pro FP aritmetiku je třeba buď přetypovat nebo použít FP konstantu (tady 100.0): */
    return gross * (taxPercentage/100.0);
  }
}

10. Napište třídu pro dynamické pole hodnot typu int. Implementujte jen metody pro přidání prvku na konec pole void add(int x) a získání hodnoty prvku int get(int i) (v případě chybného indexu by měla vyvolat výjimku). Pro implementaci použijte skutečné pole hodnot typu int, které se podle potřeby dynamicky realokuje.

Řešení:

public class DynamicArray{
  private int[] intArray = new int[0]; // Nejsnažší řešení (netřeba ošetřovat hodnotu null a/nebo vyhazovat výjimky).
  public  int   get(int i){
    /*
     * Následující přístup může vyhodit ArrayIndexOutOfBoundsException,
     * kterou nemá smysl zachytávat jen, abychom ji opět vyhodili.
     * Jedná se o runtime exception, takže se ani nedeklaruje v hlavičce.
     */
    return intArray[i];
  }
  public  void  add(int x){
    /*
     * Místo ručního kopírování lze použít:
     * - java.lang.System.arraycopy(),
     * nebo ještě lépe:
     * - java.util.Arrays.copyOf(),
     * ale to bych asi u zkoušky nedělal, neb si nepamatuju pořadí parametrů.
     */
    int[]  intArrayX  = new int[intArray.length + 1];  // (zvýšení jen o 1 je na implementaci nejjednodušší)
    int    i          = 0;
    for(int a : intArray)
      intArrayX[i++]  = a;
    intArrayX[i]      = x;
    intArray          = intArrayX;
  }
}

Přehled

Zkouším podle slajdů a dalších zdrojů sepsat přehled Javy (tj. hlavně jazyka), ne vyčerpávající, ale takový, aby stačil někomu, kdo umí C(++), a z velké části pokrýval zkouškové otázky. Můžete taky něco přihodit. — Adam

[public] [abstract] [final] class JménoTřídy [extends NějakáNadtřída] [implements NějakýInterface[, ...]] { 
  /* deklarace atributů: instančních proměnných, nebo třídních ("static") proměnných): */
  [public|protected|private] [static] [final] jménoTypu jménoProměnné;
  /* např.: */
  private boolean b;
  String s;
  /* konstruktory (jako metody, ale bez návratového typu, jméno shodné se jménem třídy) */
  /* metody: obyčejné nebo "static" (třídní, nezávislé na instanci), 
   * (mohou být přetěžovaná na základě typu parametrů, ne návratové hodnoty): */
  [public|protected|private] [static] [final] návratovýTyp|void jméno( seznamParametrů ){ 
    tělo
  }
  /* abstraktní metody (bez těla, mohou být je v abstraktní třídě): */
  abstract  [public|protected] návratovýTyp|void jméno( seznamParametrů );
}

  • Inicializace proměnných: Pokud explicitně není v deklaraci, používají se pro instanční proměnné implicitní hodnoty (false pro booleany, 0 pro číselé typy, null pro reference na objekty), lokální proměnné jsou neinicializované (pokus o přečtení hodnoty vede k chybě překladu). Pokud nevíte, k čemu všemu může být final (zvlášť u lokálních proměnných), doporučuju tohle povídání o final.
  • Viditelnost lokálních proměnných: v rámci bloku ({}), pokus o zastínění novou deklarací ve vnořeném bloku ({X x; { X x; }}) vyvolá chybu při překladu, na rozdíl od C(++).
  • Metody se volají pomocí tečky (.) (foo.doSomething(42)). Parametry se předávají hodnotou stejně jako se přiřazují hodnoty proměnným. Více viz třeba povídání na JavaRanch.com. [U primitivních typů se předá jejich skutečná hodnota, u objektů je hodnotou odkaz (tzn. odpovídá to & v C+) a toto chování nelze (narozdíl od C++) změnit. Takže pokud nechceme, aby metoda měnila objekt, je nutné explicitně vytvořit kopii, pro použití primitivních typů jako výstupních parametrů je nutné je “zakrabicovat”.]
    Dobrá poznámka k těm referencím, ale to «zakrabicování» dává smysl pouze, pokud tím myslíš zakrabicování do vlastní třídy obalující nějaký primitivní typ. Obsah objektů tříd Boolean, Integer apod. totiž stejně nelze měnit (jednak na to nejsou metody, jednak odpovídající proměnné jsou deklarované private finalAdam

    Ha, to jsem netušil. Takže děkuji za osvětlení (nebo snad osvícení?). Vojta

  • Operátory a jejich priorita je shodná s aritmetickými, relačními, logickými, bitovými a přiřazovacími operátory v C s následujícími rozdíly:
    • Bitový posun vpravo (>>>>=) doplňuje zprava opakováním «znaménkového» bitu (v C není pro znaménkové typy definováno), pro doplňování nulami slouží zvláštní operátory >>>>>>=
    • Výraz objekt instanceof TřídaNeboInterface se vyhodnotí jako true, pokud je objekt instancí dané třídy (resp. její podtřídy) nebo třídy implementující daný interface, jinak vrací false.
    • Operátory === zacházejí s referencemi na objekty (tj. všemi «objektovými» hodnotami v Javě!) jako by to byly ukazatele. (Ukazatelovou aritmetiku, porovnávání ani jiné podobné triky ovšem dělat nejde, v tom jsou reference zase jako reference v C++).
    • Logické operátory lze aplikovat jen na logické hodnoty, nedochází na rozdíl od C++ k automatické konverzi mezi číselnými typy (případně ukazateli) a boolean. (Není možné ani přetypovat: (int) true, (boolean) 1.) Bitové operátory, s výjimkou doplňku (~) naopak lze bez problémů použít na logické (boolean) hodnoty, které se pak chovají jako by měly jeden bit (1 pro true, 0 pro false, na rozdíl od C++), vede to k nezkrácenému vyhodnocení.
    • V cyklech for lze použít čárku (,) v první a třetí části (ne v podmínce), jako kdyby to byl C-čkový operátor ,, jinde ale ne, nejedná se o operátor.
    • Přetypování (typ), indexování pole pole[index], volání funkce f(args), přístup přes . a vytvoření instance pomocí new se provádí stejně jako v C (jen se formálně nejedná o operátory). Jiné operátory C(++) v Javě nejsou (::, ->, sizeof, delete, typeid, něco_cast ani už jmenovaná ,).
    • Operátory se nedají přetěžovat. Jediný, v jistém slova smyslu, přetížený operátor je operátor +, kterým lze spojovat řetězce.
  • Konstrukce pro řízení toku se liší od C++ v následujících bodech:
    • continuebreak (ale ne goto!) je možné použít spolu s návěstím pro přerušení/pokračování některého s nadřazených cyklů:
      návěstíVenku: for(...){ // vnější cyklus
        while(...){ // vnitřní cyklus
          break; 
          continue; 
          continue návěstíVenku; // pokračuje novou iterací vnějšího cyklu
        }
      }

    • U polí a tříd s iterátorem lze od JDK 5.0 použít foreach pomocí dvojtečky (není na to ale zvláštní klíčové slovo), např.: X[] poleX = new X[42]; for(X x : PoleX) /*...*/;
    • Rozskok switchem funguje pro primitivní typy byte, short, charint (a odpovídající wrapper třídy a pro výčtové typy (enum).
  • Ke zkoušce se určitě ještě podívejte na výjimky a věci související s vlákny.