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.java
cz.upol.zp3jv.lecture01.Foo
cz.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