Java - wprowadzenie
dr Dariusz Pałka
dariusz.palka@gmail.com
Obiekty w JAVIE
●
Wszystkie (prawie) byty w JAVIE to obiekty
●
Manipulowanie obiektami odbywa się poprzez
referencje do nich
Stworzenie referencji do obiektu klasy
Stworzenie referencji do obiektu klasy
String
String
:
:
String s;
Powyższa linia tworzy tylko referencje a nie obiekt,
Powyższa linia tworzy tylko referencje a nie obiekt,
co więcej referencja ta nie wskazuje na żaden
co więcej referencja ta nie wskazuje na żaden
obiekt.
obiekt.
Bezpieczniejszą techniką jest tworzenie i
Bezpieczniejszą techniką jest tworzenie i
jednoczesne inicjalizowanie referencji :
jednoczesne inicjalizowanie referencji :
String s = „abcdefgh”;
String s = „abcdefgh”;
Obiekty w JAVIE cd.
●
Trzeba tworzyć wszystkie obiekty:
String s = new String(„abcdefgh”);
String s = new String(„abcdefgh”);
Powyższa linia tworzy nowy obiekt klasy
Powyższa linia tworzy nowy obiekt klasy
String
String
i
i
przypisuje referencje do niego do zmiennej s.
przypisuje referencje do niego do zmiennej s.
Linia ta określa też jak ma być skonstruowany obiekt
Linia ta określa też jak ma być skonstruowany obiekt
klasy
klasy
String
String
– jakim ciągiem znaków ma być
– jakim ciągiem znaków ma być
zainicjalizowany
zainicjalizowany
Typy proste
-
-
-
void
IEEE754
IEEE754
64 bity
double
IEEE754
IEEE754
32 bity
float
+2
63
-1
-2
63
64 bity
long
+2
31
–1
-2
31
32 bity
int
+2
15
–1
-2
15
16 bitów
short
+127
-128
8 bitów
byte
unicode 2
16
-1
unicode 0
16 bitów
char
-
-
-
boolean
max
min
rozmiar
typ
Typy proste
Void
void
Double
double
Float
float
Long
long
Integer
int
Short
short
Byte
byte
Character
char
Boolean
boolean
‘opakowanie’ obiektowe
typ
Słowa kluczowe
abstract continue for
new
switch
assert default
if
package
synchronized
boolean do
goto
private
this
break
double
implements protected throw
byte
else
import
public
throws
case
enum
instanceof
return
transient
catch
extends int
short
try
char
final
interface
static
void
class
finally
long
strictfp
volatile
const
float
native
super
while
Zasięg nazw
Zasięg określa widzialność i czas życia zdefiniowanej nazwy.
Zasięg określa widzialność i czas życia zdefiniowanej nazwy.
Zasięg jest ograniczany przez nawiasy klamrowe
Zasięg jest ograniczany przez nawiasy klamrowe
{}
{}
.
.
Przykład:
Przykład:
{
int x = 12;
/* w tym miejscu tylko zmienna x jest dostepna */
{
int q = 96;
/* tu sa dostepne zmienne x i q */
}
/* tu tylko zmienna x jest dostepna */
/* zmienna q jest poza zasiegiem */
}
Zasięg nazw
Inaczej niż w c++ w JAVIE nie ma przykrywania
Inaczej niż w c++ w JAVIE nie ma przykrywania
zmiennych
zmiennych
Przykład:
Przykład:
{
int x = 12;
{
int x = 96; /* niepoprawne w JAVIE */
}
}
Zasięg obiektu
Zasięg obiektów jest w JAVIE inny niż typów prostych:
Zasięg obiektów jest w JAVIE inny niż typów prostych:
{
String s = new String(„abc”);
} /*koniec zasiegu */
/*
referencja s jest poza zasiegniem wiec nie
ma do niej dostepu. Natomiast obiekt
String ciagle istnieje i zajmuje pamiec
(ale nie ma do niego dostepu bo nie
istnieje już żadna referencja do niego)
*/
Garbage collector
●
W JAVIE część systemu zwana
garbage
collector
jest odpowiedzialna za usuwanie
niepotrzebnych obiektów z pamięci
●
Nie można* i nie trzeba samemu
decydować kiedy obiekt ma zostać
zniszczony.
Jedynie wiadomo kiedy obiekty typów
prostych są niszczone.
Klasy
Klasa definiuje zachowanie obiektów, będących
Klasa definiuje zachowanie obiektów, będących
instancjami tej klasy – czyli służy do definiowania
instancjami tej klasy – czyli służy do definiowania
typu:
typu:
class NazwaTypu { /*definicja*/ }
class NazwaTypu { /*definicja*/ }
Tworzenie obiektu (instancji) tej klasy:
Tworzenie obiektu (instancji) tej klasy:
NazwaTypu o = new NazwaTypu();
NazwaTypu o = new NazwaTypu();
Klasy
Klasa może zawierać dwa typy elementów:
Klasa może zawierać dwa typy elementów:
Pola
Pola
(dane) będące instancjami innych
(dane) będące instancjami innych
obiektów, lub typów prostych
obiektów, lub typów prostych
Metody
Metody
(funkcje) będące operacjami
(funkcje) będące operacjami
przeprowadzanymi na obiekcie, bądź klasie
przeprowadzanymi na obiekcie, bądź klasie
Klasy - pola
Przykład klasy zawierającej tylko
Przykład klasy zawierającej tylko
pola
pola
:
:
class Dane
class Dane
{
{
int i;
int i;
float f;
float f;
}
}
/* ... */
/* ... */
Dane d = new Dane();
Dane d = new Dane();
d.i = 32;
d.i = 32;
d.f = 23.6f;
d.f = 23.6f;
Klasy - pola
Dostęp do składowych (pól i metod) odbywa się
Dostęp do składowych (pól i metod) odbywa się
poprzez kropkę:
poprzez kropkę:
refernecjaDoObiektu.skladowa
refernecjaDoObiektu.skladowa
np.:
np.:
d.i = 32;
d.i = 32;
lub:
lub:
koloGlowne.Srodek.x = 23;
koloGlowne.Srodek.x = 23;
Klasy - pola
Diagram klasy
Diagram klasy
Dane
Dane
w UML’u
w UML’u
Klasy - metody
Metody służą do wykonywania operacji na
Metody służą do wykonywania operacji na
obiekcie (lub klasie), określają one, jakie
obiekcie (lub klasie), określają one, jakie
komunikaty rozumieją obiekty klasy.
komunikaty rozumieją obiekty klasy.
Podstawowymi składnikami metody są: nazwa,
Podstawowymi składnikami metody są: nazwa,
argumenty, zwracany typ oraz ciało metody:
argumenty, zwracany typ oraz ciało metody:
zwracanyTyp nazwaMetody(/*argumenty*/) {
zwracanyTyp nazwaMetody(/*argumenty*/) {
/* cialo metody */
/* cialo metody */
}
}
W JAVIE metody mogą być jedynie składowymi
W JAVIE metody mogą być jedynie składowymi
klas!
klas!
Klasy - metody
Przykładowa funkcja (musi być zdefiniowana
Przykładowa funkcja (musi być zdefiniowana
wewnątrz klasy) która pobiera jeden argument
wewnątrz klasy) która pobiera jeden argument
typu String i zwraca int:
typu String i zwraca int:
int foo(String s) {
int foo(String s) {
return s.length() * 2;
return s.length() * 2;
}
}
Funkcja bezargumentowa, nic nie zwracająca:
Funkcja bezargumentowa, nic nie zwracająca:
void fun() {
void fun() {
/* zrob cos */
/* zrob cos */
return; /* return może być pominiete */
return; /* return może być pominiete */
}
}
Słowo kluczowe static
Poprzedzenie składowej (pola, metody) słowem
Poprzedzenie składowej (pola, metody) słowem
static
static
oznacza, że ta składowa odnosi się do
oznacza, że ta składowa odnosi się do
klasy
klasy
a nie do
a nie do
obiektu
obiektu
.
.
Jest ono użyteczne gdy:
Jest ono użyteczne gdy:
Chcemy aby jakieś pole było współdzielone
Chcemy aby jakieś pole było współdzielone
przez wszystkie obiekty danej klasy, lub żeby
przez wszystkie obiekty danej klasy, lub żeby
istniało gdy nie istnieją jeszcze żadne obiekty
istniało gdy nie istnieją jeszcze żadne obiekty
tej klasy
tej klasy
Potrzebujemy metody, która nie jest związana
Potrzebujemy metody, która nie jest związana
z żadnym konkretnym obiektem klasy
z żadnym konkretnym obiektem klasy
Słowo kluczowe static
Przykład:
class StaticTest {
static int i = 47;
}
StaticTest st1 = new StaticTest();
StaticTest st2 = new StaticTest();
st1.i++; /* dostep przez obiekt */
StaticTest.i++; /* dostep przez klase */
Słowo kluczowe static
Przykład cd:
class StaticFun {
static void zwieksz() {
StaticTest.i++;
}
}
/* ... */
StaticFun.zwieksz();
Kompletny program w JAVIE
public class PierwszyProgram {
public static void main(String[] args) {
System.out.println(„Witaj w swiecie JAVY”);
}
}
Kompletny program w JAVIE
import java.util.*;
public class DrugiProgram {
public static void main(String[] args) {
System.out.println(„Hey, dzisiaj jest:”);
System.out.println(new Date());
}
}
Operatory
Operator przypisania ‘=‘
Operator ten przypisuje elementowi po lewej stronie
Operator ten przypisuje elementowi po lewej stronie
wartość elementu znajdującego się po prawej stronie.
wartość elementu znajdującego się po prawej stronie.
Nie można przypisywać niczego do elementów stałych:
Nie można przypisywać niczego do elementów stałych:
a = 4; /* przypisanie wartosci 4 do zmiennej a */
4 = a; /* BLAD proba przypisania do stalej */
Dla typów prostych
Dla typów prostych
przypisanie
przypisanie
oznacza
oznacza
skopiowanie
skopiowanie
zawartości.
zawartości.
Dla typów obiektowych, w przypadku których
Dla typów obiektowych, w przypadku których
manipulujemy referencjami, przypisanie oznacza
manipulujemy referencjami, przypisanie oznacza
ustawienie referencji będącej po lewej stronie operatora
ustawienie referencji będącej po lewej stronie operatora
na obiekt wskazywany przez referencję po prawej stronie
na obiekt wskazywany przez referencję po prawej stronie
operatora.
operatora.
Operator przypisania ‘=‘
Przykład:
Przykład:
class Numer {
int i;
}
public class TestPrzypisania {
public static void main(String[] args) {
Numer n1 = new Numer();
Numer n2 = new Numer();
n1.i = 10;
n2.i = 18;
n1 = n2; /*referencja n1 wsk. na obiekt w wsk. przez n2*/
n1.i = 132; /*n2.i jest tez teraz rowne 132*/
}
}
Operatory matematyczne
●
Dodawanie (+)
●
Odejmowanie (-)
●
Mnożenie (*)
●
Dzielenie (/)
●
Modulo (%)
Operatory matematyczne
Przykład:
Przykład:
a = b + c;
e = a * 7;
f -= 10; /* to samo co f = f – 10; */
g = f % 4;
/* g ma wartosc reszty z dzielenia f przez 4 */
Operatory matematyczne
Jednoargumentowe operatory ‘+’ i ‘-’
Jednoargumentowe operatory ‘+’ i ‘-’
a = -b;
d = +b;
c = a * -b;
C = a * (-b); /* bardziej czytelna wersja */
Operatory matematyczne
Auto inkrementacja (++) i dekrementacja (--)
Auto inkrementacja (++) i dekrementacja (--)
Istnieją dwie formy auto inkrementacji i
Istnieją dwie formy auto inkrementacji i
dekrementacji ‘pre’ i ‘post’
dekrementacji ‘pre’ i ‘post’
++a; /* pre-inkrementacja */
b--; /* post-dekrementacja */
Operatory matematyczne
Przykład:
Przykład:
public class AutoInc {
public static void main(String[] args) {
int a = 0;
int x = 0;
x = a++; /* x ma wartosc 0 */
x = a; /* x ma wartosc 1 */
a = 0;
x = ++a; /* x ma wartosc 1 */
x = a; /* x dalej ma wartosc 1 */
}
}
Operatory porównania
●
Operator równości (==)
●
Operator nierówności (!=)
●
Operator mniejszości (<)
●
Operator większości (>)
●
Operator ‘mniejszy lub równy’ (<=)
●
Operator ‘większy lub równy’ (>=)
Wszystkie operatory porównania zwracają
Wszystkie operatory porównania zwracają
wynik typu
wynik typu
boolean
boolean
(
(
true
true
lub
lub
false
false
)
)
Operatory porównania
Porównanie obiektów wersja 1:
Porównanie obiektów wersja 1:
public class Porownanie1 {
public class Porownanie1 {
public static void main(String[] args) {
public static void main(String[] args) {
Integer n1 = new Integer(56);
Integer n1 = new Integer(56);
Integer n2 = new Integer(56);
Integer n2 = new Integer(56);
System.out.println(n1 == n2);
System.out.println(n1 == n2);
System.out.println(n1 != n2);
System.out.println(n1 != n2);
}
}
}
}
Operatory porównania
Porównanie obiektów wersja 2:
Porównanie obiektów wersja 2:
public class Porownanie2 {
public class Porownanie2 {
public static void main(String[] args) {
public static void main(String[] args) {
Integer n1 = new Integer(56);
Integer n1 = new Integer(56);
Integer n2 = new Integer(56);
Integer n2 = new Integer(56);
System.out.println(n1.equals(n2));
System.out.println(n1.equals(n2));
}
}
}
}
Operatory
=
>
<
!
~
? :
==
<=
>=
!=
&&
||
++
--
+
-
*
/
&
|
^
%
<< >> >>>
+=
-=
*=
/=
&=
|=
^=
%=
<<=
>>=
>>>=
http://java.sun.com/docs/books/tutorial/java/nutsandbolts/opsummary.html
Wyrażenie warunkowe
Postać wyrażenia warunkowego:
Postać wyrażenia warunkowego:
boolean-exp ? value0 : value1
boolean-exp ? value0 : value1
W przypadku gdy boolean-exp ma wartość
W przypadku gdy boolean-exp ma wartość
true
true
wyrażenie przyjmuje wartość
wyrażenie przyjmuje wartość
value0,
value0,
natomiast w
natomiast w
przypadku gdy ma wartość
przypadku gdy ma wartość
false
false
wyrażenie przyjmuje
wyrażenie przyjmuje
wartość
wartość
value1
value1
.
.
Przykład:
Przykład:
static int abs(int v) {
static int abs(int v) {
return v > 0 ? v: -v;
return v > 0 ? v: -v;
}
}
Instrukcje
Instrukcje
Instrukcja pusta
;
;
Instrukcja deklaracji zmiennej
int x = 16;
int x = 16;
double[] tab = new double[100];
double[] tab = new double[100];
Instrukcja bloku programu
{
{
int x = 16;
int x = 16;
x++;
x++;
int k = 2*x;
int k = 2*x;
}
}
Instrukcje sterujące
wykonywaniem programu
Instrukcja warunkowa if-else
Składnia:
Składnia:
if( Boolean-expression )
if( Boolean-expression )
statement
statement
else
else
statement
statement
lub:
lub:
if( Boolean-expression )
if( Boolean-expression )
statement
statement
Pętla while
Składnia:
Składnia:
while( Boolean-expression )
while( Boolean-expression )
statement
statement
Pętla for
Składnia:
Składnia:
for(initialization; Boolean-exp; step)
for(initialization; Boolean-exp; step)
statement
statement
Instrukcja break
Instrukcja
Instrukcja
break
break
służy do przerywania wykonywania
służy do przerywania wykonywania
bieżącego poziomu pętli.
bieżącego poziomu pętli.
Przykład:
Przykład:
static void breakTest(int v) {
static void breakTest(int v) {
for( int i = 0; i < 100; i++ ) {
for( int i = 0; i < 100; i++ ) {
if( v/i < 10 ) break;
if( v/i < 10 ) break;
System.out.println(i)
System.out.println(i)
}
}
}
}
Instrukcja break cd.
Przykład 2:
Przykład 2:
static void breakTest2() {
static void breakTest2() {
int i = 0;
int i = 0;
while( true ) {
while( true ) {
if( i > 100 ) break;
if( i > 100 ) break;
System.out.println(i);
System.out.println(i);
i++;
i++;
}
}
}
}
Instrukcja continue
Instrukcja
Instrukcja
continue
continue
przerywa wykonywanie bieżącej
przerywa wykonywanie bieżącej
iteracji pętli i przechodzi do następnej iteracji
iteracji pętli i przechodzi do następnej iteracji
rozpoczynając od początku ciała pętli.
rozpoczynając od początku ciała pętli.
Przykład:
Przykład:
static void continueTest() {
static void continueTest() {
for( int i = 0; i < 100; i++ ) {
for( int i = 0; i < 100; i++ ) {
if( i % 10 < 2 ) continue;
if( i % 10 < 2 ) continue;
System.out.println(i)
System.out.println(i)
}
}
}
}
Instrukcja wyboru switch
Składnia:
Składnia:
switch(integral-selector) {
switch(integral-selector) {
case integral-val1: statement; break;
case integral-val1: statement; break;
case integral-val2: statement; break;
case integral-val2: statement; break;
case integral-val3: statement; break;
case integral-val3: statement; break;
//...
//...
default: statement;
default: statement;
}
}
Instrukcja wyboru switch cd.
Przykład:
Przykład:
public static void switchTest(int v) {
public static void switchTest(int v) {
int r = v %4;
int r = v %4;
switch(r) {
switch(r) {
case 0:
case 0:
System.out.println(”Podzielna przez 4”);
System.out.println(”Podzielna przez 4”);
break;
break;
case 1:
case 1:
System.out.println(”Reszta z dzielenia wynosi 1”);
System.out.println(”Reszta z dzielenia wynosi 1”);
break;
break;
// ...
// ...
}
}
}
}
Inicjalizacja i niszczenie obiektów
w Javie
Konstruktor
●
Konstruktor jest metodą klasy służącą do inicjalizacji
nowo tworzonych obiektów tej klasy.
●
Konstruktor jest automatycznie wołany gdy tworzony
jest nowy obiekt.
●
Nazwa konstruktora jest taka jak nazwa klasy do której
należy
●
Jeśli nie zdefiniuje się żadnego konstruktora to
dodawany jest automatycznie domyślny konstruktor
bezparametrowy
Konstruktor
Przykład:
Przykład:
class Kwadrat {
class Kwadrat {
Kwadrat() {
Kwadrat() {
System.out.println(”Konstruktor klasy Kwadrat”);
System.out.println(”Konstruktor klasy Kwadrat”);
}
}
}
}
public class TestKonstruktora1 {
public class TestKonstruktora1 {
public static void main(String[] args) {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
for(int i = 0; i < 10; i++)
new Kwadrat();
new Kwadrat();
}
}
}
}
Konstruktor
Przykład 2:
Przykład 2:
class Kwadrat {
class Kwadrat {
Kwadrat(int b) {
Kwadrat(int b) {
System.out.println(”Ctor klasy Kwadrat o boku ” + b);
System.out.println(”Ctor klasy Kwadrat o boku ” + b);
}
}
}
}
public class TestKonstruktora2 {
public class TestKonstruktora2 {
public static void main(String[] args) {
public static void main(String[] args) {
for(int i = 0; i < 10; i++)
for(int i = 0; i < 10; i++)
new Kwadrat(i);
new Kwadrat(i);
}
}
}
}
Konstruktor
Przykład 3:
Przykład 3:
class Kwadrat {
class Kwadrat {
Kwadrat() {
Kwadrat() {
System.out.println(”Konstruktor klasy Kwadrat”);
System.out.println(”Konstruktor klasy Kwadrat”);
}
}
Kwadrat(int b) {
Kwadrat(int b) {
System.out.println(”Ctor klasy Kwadrat o boku ” + b);
System.out.println(”Ctor klasy Kwadrat o boku ” + b);
}
}
}
}
Konstruktor
Przykład 3 cd:
Przykład 3 cd:
public class TestKonstruktora3 {
public class TestKonstruktora3 {
public static void main(String[] args) {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
for(int i = 0; i < 10; i++) {
if( i % 3 != 0 ) {
if( i % 3 != 0 ) {
new Kwadrat(i);
new Kwadrat(i);
}
}
else {
else {
new Kwadrat();
new Kwadrat();
}
}
}
}
}
}
}
}
Przeciążanie funkcji w klasie
W ramach jednej klasy nie może być dwóch
W ramach jednej klasy nie może być dwóch
metod o takich samych nazwach i odbieranych
metod o takich samych nazwach i odbieranych
parametrach.
parametrach.
Mogą natomiast istnieć dwie metody o takich
Mogą natomiast istnieć dwie metody o takich
samych nazwach ale różniące się odbieranymi
samych nazwach ale różniące się odbieranymi
parametrami – decyzja, której z nich użyć jest
parametrami – decyzja, której z nich użyć jest
podejmowana na podstawie parametrów.
podejmowana na podstawie parametrów.
Przeciążanie funkcji w klasie cd.
Przykład:
Przykład:
class P {
class P {
void foo() {
void foo() {
System.out.println(”Foo wersja 1”);
System.out.println(”Foo wersja 1”);
}
}
void foo(int i) {
void foo(int i) {
System.out.println(”Foo wersja 2”);
System.out.println(”Foo wersja 2”);
}
}
void foo(String s) {
void foo(String s) {
System.out.println(”Foo wersja 3”);
System.out.println(”Foo wersja 3”);
}
}
}
}
Przeciążanie funkcji w klasie cd.
Przykład cd.:
Przykład cd.:
public class TestPrzeciazania {
public class TestPrzeciazania {
public static void main(String[] args) {
public static void main(String[] args) {
P p1 = new P();
P p1 = new P();
p.foo(); // wersja 1
p.foo(); // wersja 1
p.foo(10); // wersja 2
p.foo(10); // wersja 2
p.foo(”Test”); // wersja 3
p.foo(”Test”); // wersja 3
}
}
}
}
Słowo kluczowe this
Słowo kluczowe
Słowo kluczowe
this
this
może być używane tylko wewnątrz
może być używane tylko wewnątrz
niestatycznych
niestatycznych
metod klasy i oznacza bieżący obiekt na
metod klasy i oznacza bieżący obiekt na
którym wykonywana jest metoda.
którym wykonywana jest metoda.
Przykład:
Przykład:
class X { void f(int i) { /*...*/ } }
class X { void f(int i) { /*...*/ } }
X a = new X(), b = new X();
X a = new X(), b = new X();
a.f(1);
a.f(1);
b.f(2);
b.f(2);
Funkcja f musi wiedzieć na którym obiekcie klasy X ma
Funkcja f musi wiedzieć na którym obiekcie klasy X ma
operować jest to możliwe dzięki przekazaniu do niej ukrytej
operować jest to możliwe dzięki przekazaniu do niej ukrytej
referencji do obiektu jako pierwszego argumentu.
referencji do obiektu jako pierwszego argumentu.
Słowo kluczowe this cd.
Ponieważ referencja do obiektu jest ukryta nie ma do niej
Ponieważ referencja do obiektu jest ukryta nie ma do niej
normalnego dostępu, jednak właśnie słowo kluczowe
normalnego dostępu, jednak właśnie słowo kluczowe
this
this
zapewnia ten dostęp.
zapewnia ten dostęp.
Normalnie nie ma potrzeby używania słowa kluczowego
Normalnie nie ma potrzeby używania słowa kluczowego
this
this
.
.
Przykład:
Przykład:
class Y {
class Y {
void f1() { /* ... */ }
void f1() { /* ... */ }
void f2() { f1(); /* ... */ }
void f2() { f1(); /* ... */ }
void f3() { this.f1(); /* ... */ }
void f3() { this.f1(); /* ... */ }
}
}
Słowo kluczowe this cd.
Przykład 2:
Przykład 2:
class Z {
class Z {
int i = 0;
int i = 0;
Z zwieksz() { i++; return this; }
Z zwieksz() { i++; return this; }
void print() { System.out.println(”i=” + i); }
void print() { System.out.println(”i=” + i); }
public static void main(String[] args) {
public static void main(String[] args) {
Z a = new Z();
Z a = new Z();
a.zwieksz().zwieksz().zwieksz().print();
a.zwieksz().zwieksz().zwieksz().print();
}
}
}
}
Wywołanie konstruktora z innego
konstruktora
Przykład:
Przykład:
class Prostokat {
class Prostokat {
int bokA = 0;
int bokA = 0;
int bokB = 0;
int bokB = 0;
Prostokat(int a, int b) {
Prostokat(int a, int b) {
bokA = a;
bokA = a;
bokB = b;
bokB = b;
}
}
// ...
// ...
Wywołanie konstruktora z innego
konstruktora cd.
// ...
// ...
Prostokat(int a) {
Prostokat(int a) {
this(a,a);
this(a,a);
}
}
Prostokat() {
Prostokat() {
this(10,10);
this(10,10);
//! this(10); // nie można wolac dwa razy
//! this(10); // nie można wolac dwa razy
}
}
}
}
Niszczenie obiektów – metoda
finalize()
●
Metoda
finalize()
jest wołana przez garbage
collector w momencie gdy obiekt ma zostać
usunięty
●
Nie należy jej wywoływać samodzielnie
●
Nie ma gwarancji, że zostanie ona zawołana
●
Jej użycie powinno być ograniczone do
zwolnienia pamięci zaalokowanej poza
mechanizmami Javy
Niszczenie obiektów
Do ‘posprzątania’ po obiekcie należy
Do ‘posprzątania’ po obiekcie należy
zaimplementować własną metodę, którą
zaimplementować własną metodę, którą
następnie należy ręcznie wywołać, gdy obiekt
następnie należy ręcznie wywołać, gdy obiekt
jest już niepotrzebny.
jest już niepotrzebny.
Inicjalizacja zmiennych
Java nie gwarantuje, że stworzona zmienna jest
Java nie gwarantuje, że stworzona zmienna jest
poprawnie zainicjalizowana. W przypadku gdy wystąpi
poprawnie zainicjalizowana. W przypadku gdy wystąpi
próba odwołania do niezainicjalizowanej zmiennej,
próba odwołania do niezainicjalizowanej zmiennej,
podczas kompilacji zostanie zgłoszony błąd.
podczas kompilacji zostanie zgłoszony błąd.
Przykład:
Przykład:
void foo() {
void foo() {
int i;
int i;
i++;
i++;
}
}
Inicjalizacja składowych obiektu
Gdy składowymi klasy są typy proste to Java domyślnie je
Gdy składowymi klasy są typy proste to Java domyślnie je
inicjalizuje:
inicjalizuje:
class Wartosci {
class Wartosci {
boolean t; // domyslna war. false
boolean t; // domyslna war. false
char c; // domyslna war. ‘\0’
char c; // domyslna war. ‘\0’
byte b; // domyslna war. 0
byte b; // domyslna war. 0
short s; // domyslna war. 0
short s; // domyslna war. 0
int i; // domyslna war. 0
int i; // domyslna war. 0
long l; // domyslna war. 0
long l; // domyslna war. 0
float f; // domyslna war. 0.0
float f; // domyslna war. 0.0
double d; // domyslna war. 0.0
double d; // domyslna war. 0.0
//...
//...
}
}
Inicjalizacja składowych obiektu
Gdy składowymi klasy są referencje do
Gdy składowymi klasy są referencje do
obiektów to domyślnie Java nadaje im wartość
obiektów to domyślnie Java nadaje im wartość
null
null
(jest to słowo kluczowe Javy).
(jest to słowo kluczowe Javy).
Inicjalizacja składowych obiektu
W Javie można do składowych przypisać wartość
W Javie można do składowych przypisać wartość
początkową inną niż wartość domyślna:
początkową inną niż wartość domyślna:
class Wartosci {
class Wartosci {
boolean t = true;
boolean t = true;
char c = ‘q’
char c = ‘q’
byte b = 10;
byte b = 10;
short s = 0xaa
short s = 0xaa
int i = 555;
int i = 555;
long l = 23
long l = 23
float f = 3.14f
float f = 3.14f
double d = 3.141592;
double d = 3.141592;
Kwadrat k = new Kwadrat(); // inicjalizacja referencji
Kwadrat k = new Kwadrat(); // inicjalizacja referencji
}
}
Inicjalizacja składowych obiektu
Można też zawołać funkcje w celu inicjalizacji zmiennej:
Można też zawołać funkcje w celu inicjalizacji zmiennej:
class Inicjalizacja {
class Inicjalizacja {
int i = f();
int i = f();
}
}
Można wołać też funkcje z parametrami, ale parametrami
Można wołać też funkcje z parametrami, ale parametrami
nie mogą być niezainicjalizowane zmienne:
nie mogą być niezainicjalizowane zmienne:
class Inicjalizacja {
class Inicjalizacja {
//! j = g(i); // blad ‘i’ nie jest zainicjalizowane
//! j = g(i); // blad ‘i’ nie jest zainicjalizowane
int i = f();
int i = f();
int j = g(i); // ok. ‘i’ jest już zainicjalizowane
int j = g(i); // ok. ‘i’ jest już zainicjalizowane
}
}
Inicjalizacja tablic
Definicja tablicy:
Definicja tablicy:
int[] t1;
int[] t1;
lub
lub
int t1[]; // definicja w stylu C
int t1[]; // definicja w stylu C
Inicjalizacja tablicy:
Inicjalizacja tablicy:
int t1[] = { 1, 5, 6, 13 };
int t1[] = { 1, 5, 6, 13 };
Możliwe jest też przypisanie jednej tablicy do drugiej,
Możliwe jest też przypisanie jednej tablicy do drugiej,
jest to przypisanie
jest to przypisanie
referencji
referencji
:
:
int[] t2;
int[] t2;
t2 = t1;
t2 = t1;
Inicjalizacja tablic cd.
Przykład:
Przykład:
public class Tablice {
public class Tablice {
public static void main(String[] args) {
public static void main(String[] args) {
int[] t1 = { 1, 2, 5, 8, 12 };
int[] t1 = { 1, 2, 5, 8, 12 };
int[] t2;
int[] t2;
t2 = t1;
t2 = t1;
for(int i = 0; i < t2.length; i++)
for(int i = 0; i < t2.length; i++)
t2[i]++;
t2[i]++;
for(int i = 0; i < t1.length; i++)
for(int i = 0; i < t1.length; i++)
System.out.println(
System.out.println(
”
”
t1[” + i + ”] = ” + t1[i] );
t1[” + i + ”] = ” + t1[i] );
}
}
}
}
Inicjalizacja tablic cd.
Możliwe jest też określenie rozmiaru inicjalizowanej
Możliwe jest też określenie rozmiaru inicjalizowanej
tablicy:
tablicy:
int[] t = new int[54];
int[] t = new int[54];
Dla typów obiektowych oprócz zainicjalizowania
Dla typów obiektowych oprócz zainicjalizowania
samej tablicy, trzeba też inicjalizować każdy
samej tablicy, trzeba też inicjalizować każdy
element tej tablicy:
element tej tablicy:
Integer[] t = new Integer[20]; // inicjalizacja tablicy
Integer[] t = new Integer[20]; // inicjalizacja tablicy
for(int i = 0; i < t.length; i++ ) {
for(int i = 0; i < t.length; i++ ) {
t[i] = new Integer(0); // inicjalizacja elementow
t[i] = new Integer(0); // inicjalizacja elementow
}
}
Tablice wielowymiarowe
Java pozwala na łatwy sposób tworzenia tablic
Java pozwala na łatwy sposób tworzenia tablic
wielowymiarowych:
wielowymiarowych:
int[][] t1 = {
int[][] t1 = {
{ 1, 2, 3},
{ 1, 2, 3},
{ 4, 5, 6},
{ 4, 5, 6},
};
};
for(int i = 0; i < t1.length; i++)
for(int i = 0; i < t1.length; i++)
for(int j = 0; j < t1[i].length; j++)
for(int j = 0; j < t1[i].length; j++)
System.out.println( ”t1[” + i + ”][” + j +
System.out.println( ”t1[” + i + ”][” + j +
”
”
] = ” + t1[i][j]);
] = ” + t1[i][j]);
//...
//...
Tablice wielowymiarowe cd.
Tworzenie tablic wielowymiarowych o określonym
Tworzenie tablic wielowymiarowych o określonym
rozmiarze:
rozmiarze:
int[][][] t2 = new int[2][2][5];
int[][][] t2 = new int[2][2][5];
Specyfikacja dostępu
Dostęp do składowych klasy
●
Jeśli nie ma określonego specyfikatora postępu to jako
domyślny przyjmowany jest „friend”, który oznacza
możliwość postępu w ramach tego samego pakietu
(pliku).
●
Specyfikator
public
oznacza, że wszyscy mają dostęp do
składowej
●
Specyfikator
private
dopuszcza dostęp do składowej
tylko w ramach tej samej klasy
●
Specyfikator
protected
dopuszcza dostęp do składowej
tylko w ramach tej samej klasy i klas z niej
dziedziczących
Dostęp do składowych klasy
Przykład:
Przykład:
public class X {
public void pub1() { /* ... */ }
public void pub2() { /* ... */ }
private void priv1() { /* ... */ }
protected void prot1() { /* ... */ }
private int i;
}
Dziedziczenie
●
W Javie możliwe jest tylko dziedziczenie
pojedyncze
●
Wszystkie obiekty w Javie dziedziczą z obiektu
podstawowego
Objects
●
Do oznaczenia dziedziczenia służy słowo
kluczowe
extends
Dziedziczenie
Przykład:
Przykład:
class A {
class A {
private String s = new String(”Klasa A”);
private String s = new String(”Klasa A”);
public void append(String str) { s += str; }
public void append(String str) { s += str; }
public void foo1() { append(” foo1()”); }
public void foo1() { append(” foo1()”); }
public void foo2() { append(” foo2()”); }
public void foo2() { append(” foo2()”); }
public void print() { System.out.println(s); }
public void print() { System.out.println(s); }
public static void main(String[] args) {
public static void main(String[] args) {
A obiekt1 = new A();
A obiekt1 = new A();
obiekt1.foo1(); obiekt1.foo2();
obiekt1.foo1(); obiekt1.foo2();
obiekt1.print();
obiekt1.print();
}
}
}
}
Dziedziczenie
Przykład cd:
Przykład cd:
public class B extends A {
public class B extends A {
public void foo2() {
public void foo2() {
append(” B.foo2()”);
append(” B.foo2()”);
super.foo2(); // wywolanie metody klasy bazowej
super.foo2(); // wywolanie metody klasy bazowej
}
}
public void foo3() { append(” foo3()”); }
public void foo3() { append(” foo3()”); }
public static void main(String[] args) {
public static void main(String[] args) {
B obiekt = new B();
B obiekt = new B();
obiekt.foo1(); obiekt.foo2(); obiekt.foo3();
obiekt.foo1(); obiekt.foo2(); obiekt.foo3();
A.main(args); // test klasy bazowej
A.main(args); // test klasy bazowej
}
}
}
}
Implementacja obiektów
public class Czytelnik {
public Czytelnik() {
}
private String imie;
private String nazwisko;
void wypozyczKsiazke(Long
identyfikatorKsiazki) {
// ... implementacja
}
void zwrocKsiazke(Long
identyfikatorKsiazki) {
// ... implementacja
}
}
Implementacja powiązań
Agregacja i kompozycja
Dziedziczenie
Dziedziczenie
Dziedziczenie
●
Dziedziczenie
–
Polimorfizm, odwołanie do metody klasy bazowej przez
super.
–
Klasy abstrakcyjne
–
Wielodziedziczenie z interfejsów
Szablony klas
●
Podobne do szablonów w C++
●
Zostały wprowadzone do języka Java w JDK 1.5
●
Przykład – 'Para'
–
Chcemy stworzyć klasę w której możemy
przechowywać dwie zmienne ('pierwszy' i 'drugi')
dowolnych typów
–
Wersja 0 – konkretne typy (np. String, String; Integer,
String; Student, Integer; itp.)
Szablony klas
●
'Para' wersja 1 – typy Object
public class ParaV1 {
public class ParaV1 {
Object pierwszy;
Object pierwszy;
Object drugi;
Object drugi;
public ParaV1(Object p, Object d) {
public ParaV1(Object p, Object d) {
pierwszy = p;
pierwszy = p;
drugi = d;
drugi = d;
}
}
public Object getPierwszy() { return pierwszy; }
public Object getPierwszy() { return pierwszy; }
public void setPierwszy(Object p) { pierwszy = p; }
public void setPierwszy(Object p) { pierwszy = p; }
//...
//...
public static void main(String[] args) {
public static void main(String[] args) {
ParaV1 para = new ParaV1("tekst", new Integer(20));
ParaV1 para = new ParaV1("tekst", new Integer(20));
String tekst = (String)para.getPierszy(); // !!!
String tekst = (String)para.getPierszy(); // !!!
}
}
}
}
Szablony klas
●
'Para' wersja 2 – klasa uogólniona (szablon)
public class ParaV2<S,T> {
public class ParaV2<S,T> {
S pierwszy;
S pierwszy;
T drugi;
T drugi;
public ParaV2(S p, T d) {
public ParaV2(S p, T d) {
pierwszy = p;
pierwszy = p;
drugi = d;
drugi = d;
}
}
public S getPierszy() { return pierwszy; }
public S getPierszy() { return pierwszy; }
public void setPierwszy(S p) { pierwszy = p; }
public void setPierwszy(S p) { pierwszy = p; }
//...
//...
public static void main(String[] args) {
public static void main(String[] args) {
ParaV2<String, Integer> p1 = new ParaV2<String,
ParaV2<String, Integer> p1 = new ParaV2<String,
Integer>("tekst", new Integer(20));
Integer>("tekst", new Integer(20));
String tekst = p1.getPierwszy();
String tekst = p1.getPierwszy();
ParaV2<Integer, Integer> p2 = new ParaV2<Integer,
ParaV2<Integer, Integer> p2 = new ParaV2<Integer,
Integer>(new Integer(0), new Integer(20));
Integer>(new Integer(0), new Integer(20));
Integer i = p2.getPierwszy();
Integer i = p2.getPierwszy();
} }
} }
Szablony klas
●
Uwagi:
–
Klasa Para przechowuje referencje do obiektów, a nie
kopie obiektów
–
Parametry dla których jest konkretyzowany szablon,
muszą być obiektowe (referencyjne), nie mogą być to
typy proste (jedna ze słabości typów uogólnionych Javy)
–
Typem jest klasa uogólniona wraz z konkretnymi
parametrami
Szablony klas
●
'Para' wersja 2 – klasa uogólniona (szablon)
public class ParaV2<S,T> {
public class ParaV2<S,T> {
//...
//...
// niepoprawna funkcja !!!
// niepoprawna funkcja !!!
void foo() {
void foo() {
pierwszy.wypozyczKsiazke(new Long(1));
pierwszy.wypozyczKsiazke(new Long(1));
}
}
}
}
Szablony klas
●
'Para' wersja 2 (szablon) – metoda zamiany na
String
public class ParaV2<S,T> {
public class ParaV2<S,T> {
//...
//...
public String toString() {
public String toString() {
return new String(”Para: [ ” + pierwszy + ”, ” +
return new String(”Para: [ ” + pierwszy + ”, ” +
drugi + ”]”);
drugi + ”]”);
}
}
}
}
Szablony klas
public class ParaV2<S,T> {
public class ParaV2<S,T> {
//...
//...
public boolean equals(Object o) {
public boolean equals(Object o) {
if (!(o instanceof Para<?,?>)) return false;
if (!(o instanceof Para<?,?>)) return false;
Para<S, T> p = (Para<S,T>)o;
Para<S, T> p = (Para<S,T>)o;
if ((getPierwszy() != null) && (getDrugi() != null))
if ((getPierwszy() != null) && (getDrugi() != null))
return getPierwszy().equals(p.getPierwszy()) &&
return getPierwszy().equals(p.getPierwszy()) &&
getDrugi().equals(p.getDrugi());
getDrugi().equals(p.getDrugi());
else
else
if ((getPierwszy() == null) && (getDrugi() == null))
if ((getPierwszy() == null) && (getDrugi() == null))
return (p.getPierwszy() == null) && (p.getDrugi() == null);
return (p.getPierwszy() == null) && (p.getDrugi() == null);
else
else
if (getPierwszy() == null)
if (getPierwszy() == null)
return (p.getPierwszy()==null) &&
return (p.getPierwszy()==null) &&
(getDrugi().equals(p.getDrugi()));
(getDrugi().equals(p.getDrugi()));
else
else
return getPierwszy().equals(p.getPierwszy()) &&
return getPierwszy().equals(p.getPierwszy()) &&
(p.getDrugi()==null);
(p.getDrugi()==null);
}
}
}
}
Szablony klas
List<String> ls = new ArrayList<String>(); // ???
List<String> ls = new ArrayList<String>(); // ???
List<Object> lo = ls; // ???
List<Object> lo = ls; // ???
lo.add(new Object());
lo.add(new Object());
String s = ls.get(0); // przypisanie Object do String
String s = ls.get(0); // przypisanie Object do String
Metody parametryzowane typami
public class TestMetody {
public class TestMetody {
<T> ParaV2<T,T> utworzPare(T v) {
<T> ParaV2<T,T> utworzPare(T v) {
return new ParaV2<T,T>(v, v);
return new ParaV2<T,T>(v, v);
}
}
void test() {
void test() {
ParaV2<Integer, Integer> p =
ParaV2<Integer, Integer> p =
utworzPare(new Integer(202));
utworzPare(new Integer(202));
}
}
}
}
Szablony klas
●
'Para' wersja 3 – klasa uogólniona z
ograniczeniami
public class ParaV3<S extends Comparable<S> ,T extends
public class ParaV3<S extends Comparable<S> ,T extends
Comparable<T> > {
Comparable<T> > {
S pierwszy;
S pierwszy;
T drugi;
T drugi;
public ParaV3(S p, T d) {
public ParaV3(S p, T d) {
pierwszy = p;
pierwszy = p;
drugi = d;
drugi = d;
}
}
public S getPierwszy() { return pierwszy; }
public S getPierwszy() { return pierwszy; }
public void setPierwszy(S p) { pierwszy = p; }
public void setPierwszy(S p) { pierwszy = p; }
// ...
// ...
}
}
Szablony klas
●
'Para' wersja 4 – klasa uogólniona z większymi
ograniczeniami
public class ParaV3<S extends Comparable<S> ,T extends
public class ParaV3<S extends Comparable<S> ,T extends
ParaV2<T,T> & Comparable<T> > {
ParaV2<T,T> & Comparable<T> > {
S pierwszy;
S pierwszy;
T drugi;
T drugi;
public ParaV3(S p, T d) {
public ParaV3(S p, T d) {
pierwszy = p;
pierwszy = p;
drugi = d;
drugi = d;
}
}
public S getPierwszy() { return pierwszy; }
public S getPierwszy() { return pierwszy; }
public void setPierwszy(S p) { pierwszy = p; }
public void setPierwszy(S p) { pierwszy = p; }
// ...
// ...
}
}
Wilcards (dżokery)
public int IloscElementow(Collection<?> c) {
public int IloscElementow(Collection<?> c) {
//...
//...
}
}
public <T> void wstaw(T elem, Collection<? super T> kol) {
public <T> void wstaw(T elem, Collection<? super T> kol) {
//...
//...
}
}
Problemy z typami uogólnionymi
●
Argumentami nie mogą być typy proste
●
Nie można tworzyć obiektów o typie będącym
parametrem typu uogólnionego
●
Nie ma pełnej informacji o typie (parametrach
typu)
Dalsza lektura
●
http://java.sun.com/j2se/1.5/pdf/generics-
tutorial.pdf
Wyjątki
●
Sytuacje wyjątkowe mogą wystąpić nawet w
bezbłędnie napisanych programach. Przykłady:
–
Błędne dane podane przez użytkownika (np. obliczanie
pierwiastka kwadratowego, rzeczywistego z ujemnej
liczby)
–
Brak miejsca na dysku do zapisania danych
–
Brak pamięci
●
Program (i język programowania) powinien
umożliwiać obsługę takich sytuacji wyjątkowych.
●
Zazwyczaj nie jest możliwa
Wyjątki
●
Program składa się z wielu modułów, dodatkowo
moduły mogą pochodzić z różnych bibliotek
–
problemy:
●
autor biblioteki może wykryć błędy czasu wykonywania, ale
nie wie co z nimi zrobić
●
użytkownik biblioteki może wiedzieć, jak postępować z
takimi błędami, lecz nie może ich wykryć – gdyby mógł
obsłużyłby je we własnym kodzie
–
rozwiązanie - rozdzielenie obsługi błędów na:
●
powiadamianie o błędnych warunkach, których nie można
obsłużyć lokalnie
●
obsługę błędów wykrytych gdzie indziej
Wyjątki w Javie
public class Wyjatek {
public class Wyjatek {
void metoda(boolean x) throws Exception {
void metoda(boolean x) throws Exception {
if(x == false) throw new Exception();
if(x == false) throw new Exception();
}
}
public static void main(String[] args) throws Exception {
public static void main(String[] args) throws Exception {
Wyjatek w = new Wyjatek();
Wyjatek w = new Wyjatek();
System.out.println("przed metoda");
System.out.println("przed metoda");
w.metoda(false);
w.metoda(false);
System.out.println("po metodzie");
System.out.println("po metodzie");
}
}
}
}
Wyjątki w Javie
przed metoda
przed metoda
Exception in thread "main" java.lang.Exception
Exception in thread "main" java.lang.Exception
at Wyjatek.metoda(Wyjatek.java:3)
at Wyjatek.metoda(Wyjatek.java:3)
at Wyjatek.main(Wyjatek.java:9)
at Wyjatek.main(Wyjatek.java:9)
●
Wynik działania:
Wyjątki w Javie
public class Wyjatek {
public class Wyjatek {
void metoda(boolean x) throws Exception {
void metoda(boolean x) throws Exception {
if(x == false) throw new Exception();
if(x == false) throw new Exception();
}
}
public static void main(String[] args) throws Exception {
public static void main(String[] args) throws Exception {
Wyjatek w = new Wyjatek();
Wyjatek w = new Wyjatek();
System.out.println("przed metoda");
System.out.println("przed metoda");
try {
try {
w.metoda(false);
w.metoda(false);
} catch(Exception ex) {
} catch(Exception ex) {
System.out.println("Obsluga Wyjatku");
System.out.println("Obsluga Wyjatku");
ex.printStackTrace(System.out);
ex.printStackTrace(System.out);
}
}
System.out.println("po metodzie");
System.out.println("po metodzie");
}
}
}
}
Wyjątki w Javie
przed metoda
przed metoda
Obsluga Wyjatku
Obsluga Wyjatku
java.lang.Exception
java.lang.Exception
at Wyjatek.metoda(Wyjatek.java:3)
at Wyjatek.metoda(Wyjatek.java:3)
at Wyjatek.main(Wyjatek.java:10)
at Wyjatek.main(Wyjatek.java:10)
po metodzie
po metodzie
●
Wynik działania:
Wyjątki
●
Zgłaszanie wyjątku w czasie obsługi catch
●
Ponowne zgłaszanie obsługiwanego wyjątku
void foo() throws Exception {
try {
bar();
} catch (Exception e) {
throw e;
}
}
Wyjątki
●
Blok 'finally'