Každá veřejná třída je umístěna v samostatném souboru, který nese stejné jméno jako třída, tj. třída Foo, je umístěna v souboru Foo.java. Název třídy začíná vždy velkým písmenem. V názvech se nepoužívají "_" (podtržítka).
Jednotlivé třídy jsou umísťovány do balíčků, které představují:
cz/upol/zp3jv/lecture02/Foo.javacz.upol.zp3jv.lecture01.Foocz.upol.zp3jv.lecture01.Foo a edu.mit.Foo jsou odlišné třídypublic class Foo {
// deklarace atributu (clenskych promennych)
// konstruktory
// metody
}
<viditelnost> <modifikátory> <typ> <jméno> [ = inicializační hodnota ];
public - atribut je přístupný z jakékoliv třídyprivate - atribut je přístupný pouze ze třídy, ve které je deklarovanprotected - atribut je přístupný ze třídy, kde je deklarovan, jejich potomků a ze tříd, které se nachází ve stejném balíčkustatic - atribut deklarovaný jako static je chápan jako atribut třídy (je sdílená všemi instancemi dané třídy)final - atribut se nebude měnit (konstanta)age, numberOfLegs)SPEED_OF_LIGHT)private int foo;
public double answerToUltimateQuestionOfLife = 42.0;
public static final int SPEED_OF_LIGHT = 299792458;
this a super odkazující na aktuální objekt a na objekt předka.private a přistupuje se k nim pomocí vyčleněnných metod, tzv. getterů a setterů.<viditelnost> <modifikátory> <návratový-typ> <jméno-metody>([typ-1 argument-1, [ typ-2 argument-2, ... [ typ-N arugment-N ]]]) {
// tělo metody
}
static - jedná se o metodu třídy (metoda je přístupná bez vytvoření instance dané třídy)final - metodu nepůjde překrýt v potomkoviabstract - jedná se o abstraktní metodu, která nemá tělo; pokud třída obsahuje takovou metodu, je nutné samotnou třídu deklarovat jako abstraktní, tzn. public abstract class Foo.Poznámka: Statické metody by měly být používány pouze v opodstatněných případech. Tedy pouze tehdy pokud má smysl volat danou metodu, bez existující instance!
private int add(int a, int b) {
return a + b;
}
public void printMsg(String msg, int count) {
for (int i = 0; i < count; i++) {
System.out.println(msg);
}
}
<viditelnost> NazevTridy([typ-1 argument-1, [ typ-2 argument-2, ... [ typ-N arugment-N ]]]) {
// zavolani rodicovskeho konstruktoru
super(...);
// tělo konstruktoru
// typicky inicializace proměnných
}
Poznámka: Třída může mít více metod a konstruktorů stejného jména. V takovém případě se rozhodne o tom, která metoda/konstruktor bude zavolána na základě předaných typů argumetů.
public void print(int number) {
System.out.println("Int: " + number);
}
public void print(String str) {
System.out.println("String: " + str);
}
Vytvoření nové instance třídy se provádí pomocí operátoru new. Např.:
Foo foo = new Foo();
K metodám a proměnným dané třídy se přistupuje pomocí operátoru . Např.:
foo.bar = 42;
foo.baz(42);
Příklad třídy, představující nějaké obecné zvíře:
public class Animal {
private int legs;
private int age;
public Animal(int legs, int age) {
super();
this.legs = legs;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getLegs() {
return legs;
}
}
public class Example1 {
public static main(String[] args) {
Animal dog = new Animal(4, 6);
Animal penguin = new Animal(2, 1);
System.out.println(dog.getLegs() + penguin.getLegs());
}
}
V Javě může třída dědit pouze z jednoho předka. Z pohledu dědičnosti všechny třídy tvoří souvislou hierarchii, kde na vrcholu je třída Object.
Dědění se deklaruje pomocí klíčového slova extends a názvu třídy, např.:
public class Bar extends Foo { /*...*/ }.
public class Dog extends Animal {
public static final int OLD_DOG = 10;
// predpokladame, ze kazdy pes ma ctyri nohy
public Dog(int age) {
super(4, age);
}
// nove pridana metoda
public void fetch() {
if (getAge() < OLD_DOG) System.out.println("Your dog is fetching a stick");
else System.out.println("Your dog is ignoring you.");
}
}
public class Example2 {
public static main(String[] args) {
Dog dog = new Dog(6);
Animal penguin = new Animal(2, 1);
System.out.println(dog.getLegs() + penguin.getLegs());
}
}
class je použito klíčové slovo interface a jednotlivé metody nejsou deklarovány jako abstract. Např.
public interface Foo {
public void bar();
public int baz(int a, int b);
}
Implementace daného rozhraní se deklaruje pomocí kličového slova implements.
public class Bar implements Foo { /* ... */ }
Příklad:
public interface Noisy {
public void makeSound();
}
public class BigDog extends Dog implements Noisy {
public BigDog(int age) {
super(age);
}
public void makeSound() {
System.out.println("Haf Haf\n");
}
}
public class Duck extends Animal implements Noisy {
public Duck(int age) {
super(2, age);
}
public void makeSound() {
System.out.println("Ga Ga\n");
}
}
Poznámka: Díky polymorfismu můžeme ke každému objektu přistupovat, jako by se jednalo o některého z jeho rodičů, potažmo by se jednalo o objekt implementující dané rozhranní.
BigDog bigDog = new BigDog(10);
Duck duck = new Duck(3);
bigDog.fetch();
bigDog.makeSound();
duck.makeSound();
Noisy noisyAnimal = new BigDog(10);
noisyAnimal.makeSound();
Ověření, že daný objekt je instance nějaké třídy nebo že implementuje nějaké rozhranní jde pomocí operátoru instanceof. Často se používá v kombinaci s přetypováním.
if (noisyAnimal instanceof Dog)
((Dog) noisyAnimal).fetch();
public static int max(int first, int... rest) {
}
Kompilátorem převedeny na public static int max(int first, int[] rest) {}. V praxi je tedy volání max(1,2,3) přeloženo na max(1, new int[] {2, 3}).
Přestože rozhraní má představovat pouze ,,kontrakt'', jaké metody daná implementace nabízí a nemělo by obsahovat žádné implementované metody, od Javy 8 je možné v rozhraní implementovat metody označené jako static a metody označené jako default. Metody označené jako default představují implicitní implementaci dané metody a mohou být v implementujících třídách překryty. Tyto metody narušují základní myšlenku rozhraní, ale byly zavedeny proto, aby mohlo dojít k rozšíření existujících rozhraní bez narušení kompatibility s existujícími implementacemi.
Soubory neformátované dle konvencí budou vráceny k přepracování!
Implementujte třídu Point představující bod v rovině určený dvěma souřadnicemi. V tříde Point implementujte metodu double distance(Point p) vracející vzdálenost od daného bodu.
Implentujte třídu Line představující úsečku. Implementujte metody: double getLength() a double distance(Point p). Vzdálenost bodu od úsečky berte v tomto případě jako nejmenší vzdálenost mezi bodem a všemi body ležícími na úsečce.
Implementujte třídu Rectangle představující obdelník, který má strany vodorovné s osami X a Y. Třída by měla mít dva konstruktory, jeden vytvářející obdelník pomocí dvou bodů, další vytvářející obdelník na základě bodu, výšky a šířky. Implementujte metodu double getArea() vracející obsah daného obrazce. Implementujte metodu double distance(Point p) vracející vzdálenost od daného bodu. Vzdálenost bodu od obdelníku berte v tomto případě jako nejmenší vzdálenost mezi bodem a všemi body ležícími na stranách obdelníku.
Implementujte třídu Square představující čtverec. Třída by měla mít konstruktor vytvářející objekt na zákládě souřadnice a délky strany. Implementujte metodu double getArea(). Implementujte metodu double distance(Point p) vracející vzdálenost od daného bodu.
Implementujte třídu Circle představující kružnici. Třída by měla mít konstruktor vytvářející objekt na zákládě souřadnice a poloměru. Implementujte metodu double getArea(). Implementujte metodu double distance(Point p) vracející vzdálenost od daného bodu. Vzdálenost bodu od kružnice berte v tomto případě jako nejmenší vzdálenost mezi bodem a všemi body ležícími na kružnici. Vzdálenost nemůže mít zápornou hodnotu!
Třídy z předchozích příkladů upravte tak, aby se díky dědičnosti omezila redundance kódu. Pokud to má opodstatnění, použijte rozhraní.
© Martin Trnečka