Predavanje
br. index|1|2|3|4|5|6|7|8|9|10|11|12|13|14|HOME
Aplikacija Hello World – kompiliranje i izvršavanje programa – for-petlje – operatori za increment i decrement – naredbe za ispis – Fibonaccijevi brojevi – varijable i tipovi podataka – komentari –argumenti na komandnoj liniji – klase, atributi i metode – objekti – razlikovanje objekata iste klase – višestruko referenciranje objekta – statièke varijable – metode –prenošenje argumenta u metodu – vraæanje vrijednosti iz metoda – setter metode – getter metode – ista imena varijabli i metoda – konstruktori – skrivanje imena varijabli i kljuèna rijeè this – polja
class HelloWorld {
public static void main (String args[]) {
System.out.println("Hello World!");
}
}
Tri su koraka u stvaranju programa:
Pod UNIXom kompilacija i izvršavanje izgleda ovako:
% javac HelloWorld.java
% java HelloWorld
Hello World
%
Na raèunalu student.math.hr se Java kompajler (javac), Java interpreter (java) i ostali alati nalaze u direktoriju /opt/java/bin, dakle dodajte taj direktorij u vašu $PATH varijablu:
% export PATH=$PATH:/opt/java/bin
Pod Windowsima slièno; mora se koristiti DOS-shell:
C:> javac HelloWorld.java
C:> java HelloWorld
Hello World
C:>
Pri tom opet varijabla PATH koja se definira u odgovarajuæem retku datoteke autoexec.bat ili pomoæu
Start à Settints à System à Environment Variables à PATH
mora sadržavati odgovarajuæi direktorij, npr …;c:\jdk1.3.0_02\bin\;…
Primijetite uporabu .java ekstenzije kod kompiliranja, ali ne i .class ekstenzije kod izvršavanja.
class Count {
public static void main (String args[]) {
int i;
for (i = 0; i < 50; i=i+1) {
System.out.println(i);
}
}
}
Deklaracija varijabli unutar petlje
class Count {
public static void main (String args[]) {
for (
int i = 0; i < 50; i = i+1) {
System.out.println(i);
}
}
}
Java ima operatore ++ i -- kao C.
Increment:
class Count {
public static void main (String args[]) {
for (int i = 0; i < 50;
i++) {
System.out.println(i);
}
}
}
Decrement:
class Count {
public static void main (String args[]) {
for (int i = 50; i > 0;
i--) {
System.out.println(i);
}
}
}
class PrintArgs {
public static void main (String args[]) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
% java PrintArgs Hello there!
Hello
there!
%
Za
ispis retka koriste se metode println(...)
iz klase PrintStream.
U našem programu
System.out.println()
ispisuje sadržaj standardnog output
streama System.out
klase System,
u ovom sluèaju argumente iza kojih slijedi line-separator ovisan o
platformi ([carriage return] (ASCII 13, \r) i [linefeed] (ASCII 10, \n) na Windowsima, [linefeed] na UNIXu, [carriage
return] na Mac-u)
System.err.println(…)
ispisuje sadržaj sa standardnog error output streama System.err
.
Možete
konkatenirati argumente za println()
pomoæu znaka +, npr.
System.out.println("Ucitano je " + args.length + "argumenata s komandne linije");
Ako
koristite print(…)
umjesto println()
onda nakon ispisa nema znaka za novi redak. Npr,
System.out.print("Ucitano je ");
System.out.print(args.length);
System.out.print(" argumenata s komandne linije");
System.out.println();
System.out.println()
prekida liniju i pokreæe ispis. U pravilu se ništa neæe ispisati na ekranu dok
god se ne pojavi znak za prijelom linije.
class Fibonacci {
public static void main (String args[]) {
int low = 1;
int high = 0;
System.out.println(low);
while (high < 50) {
System.out.println(high);
int temp = high;
high = high + low;
low = temp;
}
}
}
Primjer pokazujue zbrajanje, while-petlju, relacije te deklaracije i pridruživanje varijabli.
U javi postoji 8 primitivnih tipova podataka:
boolean
byte
short
int
long
float
double
char
Meðutim
postoji samo 7 vrsta literala, a jedan meðu njima (String
)
nije primitivni tip podataka:
boolean
: true
ili falseint
: 89,
-945, 37865long
:
89L, -945L, 5123567876Lfloat
:
89.5f, -32.5f,double
:
89.5, -32.5, 87.6E45char
:
'c', '9', 't'String
: "Ovo
je string literal"Ne
postoje literali tipa short
ili byte
.
String
je referentni
ili objektni tip, ne primitivni. Meðutim, java kompajler ima posebnu
podršku za String
ove,
pa može izgledati kao da je to primitivni tip.
class Variables {
public static void main (String args[]) {
boolean b = true;
int low = 1;
long high = 76L;
long middle = 74;
float pi = 3.1415292f;
double e = 2.71828;
String s = "Hello World!";
}
}
Komentari se u Javi oznaèavaju na isti naèin kao u C++. Sve izmeðu /* i */ æe se ignorirati, a u pojedinaènim linijama bit æe odbaèeno sve nakon // (do kraja linije). Takoðer postoji poseban oblik komentara za javadoc – alat za automatizirano dokumentiranje java programa. Pišu se izmeðu znakova /** i */.
/**
* Ovako se pisu komentari za javadoc
*/
class HelloWorld {
public static void main (String args[]) {
/* Ispisujemo liniju Hello World */
System.out.println("Hello World!");
}
// main metoda ovdje zavrsava
}
// HelloWorld program ovdje zavrsava
Komentari se evaluiraju u znak space (praznina), a ne u ništa. Zato bi sljedeæi primjer izazvao grešku u kompiliranju:
int i = 78/* Razdvoji broj na dva dijela */76;
Java ovo pretvara u pogrešnu naredbu
int i = 78 76;
a ne u
int i = 7876;
class printArgs {
public static void main (
String args[]) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
Ime klase nije ukljuèeno u listu argumenata. Argumenti se s komandne linije prenose u program kao polje stringova. Poèetna komponenta svakog polja uvijek je nulta. Npr,
% java printArgs Hello There
args[0]
je
string "Hello"
.
args[1]
je
string "There"
.
args.length
je
2.
Svi argumenti s komandne linije prenose se kao stringovi, nikad kao brojevi. Kasnije æete nauèiti pretvarati stringove u brojeve.
Klasa je obrazac ili prototip koji definira varijable
i metode zajednièke svim objektima neke vrste
Atribuiti kažu što neki objekt jest.
Metode kažu što neki objekt radi.
class TwoDPoint {
double x;
double y;
}
Da
biste kompilirali tu klasu, spremite je u datoteku TwoDPoint.java
i otipkajte:
% javac TwoDPoint.java
Primijetite da ovo nije kompletan program. Ne možete ga, naime, izvršiti jer mu nedostaje main() metoda.
Objekt je primjerak (instanca) klase.
Objekte
možete kreirati pomoæu kljuène rijeèi new
iza koje slijedi tzv. konstruktor
klase. Sljedeæi program kreira objekt tipa TwoDPoint
i ispisuje njegove
atribute:
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin; // ovime smo deklarirali (ne i alocirali) objekt origin
origin = new TwoDPoint(); // sada smo uz pomoc konstruktora alocirali (kreirali objekt)
origin.x = 0.0; // Inicijaliziramo njegove atribute
origin.y = 0.0;
// Ispisujemo podatke o objektu origin
System.out.println("Ishodiste ima koordinate " + origin.x + ", " + origin.y);
} // kraj main() metode
} // kraj OriginPrinter programa (klase)
Tocka
.
je tzv. separator pristupa èlanovima.
Poziv konstruktora uz kljuènu rijeè new
potreban je za alociranje objekta.
Stavite ovu klasu u datoteku OriginPrinter.java u istom direktoriju kao TwoDPoint.java, kompajlirajte je i izvršite (to je sada kompletan program):
% javac OriginPrinter.java
% java OriginPrinter
Ishodiste ima koordinate 0.0, 0.0
%
Opæenito, klase æe imati više od jednog objekta. Za razlikovanje objekata unutar iste klase koriste se referentne varijable. Sljedeæi program kreira dva razlièita objekta tipa TwoDPoint i ispisuje njihove atribute.
class TwoPointPrinter {
public static void main(String[] args) {
TwoDPoint origin; // deklariramo tocku origin
TwoDPoint one; // deklariramo tocku one
origin = new TwoDPoint(); // alociramo origin pomocu konstruktora klase
one = new TwoDPoint(); // alociramo one pomocu konstruktora klase
// postavljamo vrijednosti atributa
origin.x = 0.0;
origin.y = 0.0;
one.x = 1.0;
one.y = 0.0;
// ispisujemo koordinate ovih dviju tocaka
System.out.println("Ishodiste ima koordinate " + origin.x + ", " + origin.y);
System.out.println("Tocka one ima koordinate " + one.x + ", " + one.y);
} // kraj main() metode
} // kraj TwoPointPrinter programa (klase)
Obrada:
% javac TwoPointPrinter.java
% java TwoPointPrinter
Ishodiste ima koordinate 0.0, 0.0
Tocka one ima koordinate 1.0, 0.0
%
Variable
one
i origin
su dvije razlièite referentne varijable koje pokazuju na dva razlièita objekta.
Nije dovoljno samo identificirati varijablu kao èlana klase, veæ treba
specificirati na koji objekt u toj klasi se ona referira.
Moguæe je da dvije referentne varijable pokazuju na isti objekt. Kad na neki objekt ne pokazuje ni jedna referentna varijabla, on æe biti oznaèen za uklanjanje (garbage collection). Sljedeæi program deklarira dvije referentne varijable tipa TwoDPoint, kreira jedan objekt tipa TwoDPoint i pridružuje taj objekt objema varijablama. Te se dvije varijable smatraju jednakima.
class EqualPointPrinter {
public static void main(String[] args) {
TwoDPoint origin1; // deklariramo tocku origin1
TwoDPoint origin2; // deklariramo tocku origin2
origin1 = new TwoDPoint(); // alociramo origin1 pomocu konstruktora klase
origin2 = origin1; // definiramo jos jednu referentnu varijablu za origin1
// Postavljamo vrijednosti atributa (
samo za origin1)
origin1.x = 0.0;
origin1.y = 0.0;
// print
System.out.println("Tocka origin1 ima koordinate " + origin1.x + ", " + origin1.y);
System.out.println("Tocka origin2 ima koordinate " + origin2.x + ", " + origin2.y);
} // kraj main() metode
} // kraj EqualPointPrinter programa (klase)
Obrada i izlaz:
% javac EqualPointPrinter.java
% java EqualPointPrinter
Tocka origin1 ima koordinate 0.0, 0.0
Tocka origin2 ima koordinate 0.0, 0.0
%
Primijetite
da su origin1
i origin2
dvije razlièite referentne varijable koje referenciraju isti objekt tipa point
.
Statièka varijabla je varijabla klase, ona pripada klasi (samoj klasi), a ne nekom objektu (instanci klase).
class Point {
double x;
double y;
static double xorigin = 0.0;
static double yorigin = 0.0;
}
class PointPrinter {
public static void main (String [] args) {
System.out.println("Ishodiste je u tocki (" +
Point.xorigin + ", " +
Point.yorigin + ")");
}
}
Obrada:
% javac Point.java
% javac PointPrinter.java
% java PointPrinter
Ishodiste je u tocki (0.0, 0.0)
%
Primijetite da za ispis statièkih varijabli nije bilo potrebno kreirati konkretni objekt. Varijablama klase pristupa se pomoæu imena klase, a ne pomoæu imena referentne varijable.
Metode kažu što neki objekt radi.
class TwoDPoint {
double x;
double y;
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
Primijetite
da se kljuèna rijeè this
koristi kako bi se iznutra referencirala varijabla koja pripada istoj klasi.
Sada možemo preraditi program OriginPrinter ovako:
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint();
origin.x = 0.0;
origin.y = 0.0;
origin.print();
}
}
Obrada:
% javac OriginPrinter.java
% java OriginPrinter
(0.0, 0.0)
%
Dodat æemo klasi TwoDPoint još jednu metodu za ispis.
class TwoDPoint {
double x;
double y;
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
}
Primijetite
da su tu dvije razlièite print()
metode. Jedna prihvaæa argument, druga ne. To je dozvoljeno dok god lista
argumenata razrješuje ovu dvosmislenost. To se naziva overloading. Metoda System.out.println()
takoðer primjer overloaded
metode. Metoda
main(String[] args)
je non-overloaded metoda koja ima
polje Stringova
kao argumente.
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint();
origin.x = 0.0;
origin.y = 0.0;
origin.print();
origin.print(5);
}
}
Izlaz:
% javac TwoDPoint.java
% javac OriginPrinter.java
% java OriginPrinter
(0.0,0.0)
(0.0,0.0)
(0.0,0.0)
(0.0,0.0)
(0.0,0.0)
(0.0,0.0)
%
Još jednom æemo klasi TwoDPoint dodati novu metodu za ispis, getAsString() koja za razliku od prethodne dvije ima povratni tip (return type) i vraæa vrijednost tipa String.
class TwoDPoint {
double x;
double y;
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
String getAsString() {
return "(" + this.x + "," + this.y + ")";
}
}
Zato sad ovu metodu možemo koristiti na svim mjestima gdje bi inaèe došla vrijednost tipa String, npr,
String s = origin.getAsString();
System.out.println(s);
Ili, još bolje,
System.out.println(origin.getAsString());
Sada možemo još jednom preraditi klasu OriginPrinter:
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint();
origin.x = 0.0;
origin.y = 0.0;
System.out.println(origin.getAsString());
}
}
Imamo:
% javac TwoDPoint.java
% javac OriginPrinter.java
% java OriginPrinter
(0.0,0.0)
%
Takoðer poznate i kao “mutator” metode, ove metode samo postavljaju vrijednosti varijabli (obièno privatnih) unutar klase.
class TwoDPoint {
double x;
double y;
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
String getAsString() {
return "(" + this.x + "," + this.y + ")";
}
void setX(double value) {
this.x = value;
}
void setY(double value) {
this.y = value;
}
}
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint();
origin.setX(0.0);
origin.setY(0.0);
System.out.println(origin.getAsString());
}
}
Imamo opet:
% javac TwoDPoint.java
% javac OriginPrinter.java
% java OriginPrinter
(0.0,0.0)
%
Takoðer poznate i kao accessor metode, ove metode samo vraæaju vrijednosti varijebli unutar klase.
class TwoDPoint {
double x;
double y;
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
String getAsString() {
return "(" + this.x + "," + this.y + ")";
}
void setX(double value) {
this.x = value;
}
void setY(double value) {
this.y = value;
}
double getX() {
return this.x;
}
double getY() {
return this.y;
}
}
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint();
origin.setX(0.0);
origin.setY(0.0);
System.out.println("(" + origin.getX() + "," + origin.getY() + ")");
}
}
Još jednom:
% javac TwoDPoint.java
% javac OriginPrinter.java
% java OriginPrinter
(0.0,0.0)
%
Java èak dozvoljava da varijable i metode imaju ista imena tako dugo dok se razlikuju po listi argumenata i povratnom tipu. Npr. klasi TwoDPoint koja sadrži attribute x i y možemo dodati i istoimene accessor metode bez opasnosti od dvoznaènosti:
class TwoDPoint {
double x;
double y;
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
String getAsString() {
return "(" + this.x + "," + this.y + ")";
}
void setX(double value) {
this.x = value;
}
void x(double value) {
this.x = value;
}
void setY(double value) {
this.y = value;
}
void y(double value) {
this.y = value;
}
double getX() {
return this.x;
}
double x() {
return this.x;
}
double getY() {
return this.y;
}
double y() {
return this.y;
}
}
Sada možemo umjesto setX(value) koristiti x(value), a umjesto getX() staviti x() i analogno za y. tako da OriginPrinter može izgledati i ovako:
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint();
origin.x(0.0);
origin.y(0.0);
System.out.println("(" + origin.x() + "," + origin.y() + ")");
}
}
Još jednom:
% javac TwoDPoint.java
% javac OriginPrinter.java
% java OriginPrinter
(0.0,0.0)
%
Konstruktori služe za instanciranje klasa, dakle kreiranje objekata koji su instance neke klase. To su posebne metode koje imaju isto ime kao njihova klasa i ne vraæaju nikakvu vrijednost. Npr.:
class TwoDPoint {
double x;
double y;
TwoDPoint(double xvalue, double yvalue) { // konstruktor sa dva argumenta
this.x = xvalue;
this.y = yvalue;
}
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
String getAsString() {
return "(" + this.x + "," + this.y + ")";
}
void setX(double value) {
this.x = value;
}
void x(double value) {
this.x = value;
}
void setY(double value) {
this.y = value;
}
void y(double value) {
this.y = value;
}
double getX() {
return this.x;
}
double x() {
return this.x;
}
double getY() {
return this.y;
}
double y() {
return this.y;
}
}
U jednoj klasi može biti i više konstruktora. Svaki konstruktor zadaje po jedan naèin kreiranja objekata dane klase.
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint(0.0, 0.0);
System.out.println("(" + origin.x() + "," + origin.y() + ")");
}
}
Izlaz:
% javac TwoDPoint.java
% javac OriginPrinter.java
% java OriginPrinter
(0.0,0.0)
%
this
Pomoæu
kljuène rijeèi this
moguæe je èak i argumentima konstruktora (ili bilo koje druge metode) davati
ista imena kao varijablama. Npr.;
TwoDPoint(
double x, double y) {
this.x = x;
this.y = y;
}
void setX(
double x) {
this.x = x;
Klasu TwoDPoint možemo, dakle preraditi ovako:
class TwoDPoint {
double x;
double y;
TwoDPoint(double
x, double
y) { // konstruktor sa dva argumenta
this.x = x;
this.y = y;
}
void print() {
System.out.println("(" + this.x + "," + this.y + ")");
}
void print(int n) {
for (int i = 0; i < n; i++) {
System.out.println("(" + this.x + "," + this.y + ")");
}
}
String getAsString() {
return "(" + this.x + "," + this.y + ")";
}
void setX(double
x) {
this.x = x;
}
void x(double
x) {
this.x = x;
}
void setY(double
y) {
this.y = y;
}
void y(double
y) {
this.y = y;
}
double getX() {
return this.x;
}
double x() {
return this.x;
}
double getY() {
return this.y;
}
double y() {
return this.y;
}
}
Kažemo
da unutar metode, deklaracija lokalne varijable ili argumenta sa istim imenom
kao neka (member) varijabla skriva
ili zasjenjuje (hides)tu
varijablu. Ona se može referencirati dodavanjem prefiksa this
.
Polje
je kolekcija varijabli istog tipa. Npr. args[]
u main()
metodi je polje objekata
tipa String
.
Zamislimo klasu koja broji pojavljivanja znamenaka 0-9. Pretpostavimo da želimo testirati da li je raspodjela brojeva koje generira generator sluèajnih brojeva doista uniformna. Ako jest, sve znamenka bi trebale imati približno istu frekvenciju nakon duljeg vremena.
Napravit
æemo polje ndigits
od 10 elemenata. Nulti element æe pratiti broj pojavljivanja nula, prvi element
broj pojavljivanja jedinica itd. Koristit æemo klasu java.util.Random.
Za generiranje sluèajnih brojeva koristit æemo metodu nextDouble()
iz te klase.
import java.util.Random;
class RandomTest {
public static void main (String args[]) {
int[] ndigits = new int[10];
double x;
int n;
Random myRandom = new Random();
for (int i = 0; i < 10; i++) { // inicijaliziranje polja
ndigits[i] = 0;
}
for (long i=0; i < 100000; i++) { // testiranje generatora slucajnih brojeva
x = myRandom.nextDouble() * 10.0; // novi slucajni broj izmedju 0 i 9
n = (int) x; // pretvaranje u cijeli broj
ndigits[n]++; // biljezimo pojavu dobivenog slucajnog broja
}
for (int i = 0; i < 10; i++) { // ispis rezultata
System.out.println(i+": " + ndigits[i]);
}
}
}
Ispis može izgledati otprilike ovako:
% javac RandomTest.java
% java RandomTest
0: 9967
1: 9808
2: 10069
3: 10057
4: 9984
5: 9932
6: 10004
7: 10128
8: 9952
9: 10099
%
U programu su tri for-petlje: jedna za inicijaliziranje polja, druga za izvoðenje odgovarajuæih raèuna i treæa za ispis rezultata. To je uobièajeno u programima koji koriste polja.