Internet Programiranje -JSP

JSP

1. JSP pages typically comprise of:

2. Static HTML/XML components.

3. Special JSP tags

Najčešće, delovi Java koda u okviru JSP stranice se nazivaju „scriptlets.“

JSP stranica se može kreirati pomoću standardnih HTML/XML alata, ali treba naglasiti da je JSP specifikacaija standardni deo Java Servlet API. Zbog ove činjenice u radu sa JSP stranicama iskustvo i znanje o servletima je veom akorisno. Ipak, postoje značajne razlike izmđu ove dve tehnologije. Za razliku od servleta, gde je za programiranje potrebno značajno programersko znanje, JSP tehnologija je mnogo bliža i manje iskusnim programerima, ali i dizajnerima korisničkog interfejsa. Na ovaj način i dizajneru mogu da dobiju značajajniju ulogu u toku razvoja same aplikacije. Još jedna prednost JSP tehnologije je efikasno korišćenje odvojenih nezavisnih programskih segmenata. Time do punog izražaja dolaze sve osobine objektno orijentisanog programiranja. Nezavisni programski segmenti se definišu u okviru komponenata zvanih JavaBeans, a tehnologija koja ih koristi je Enterprise JavaBeans tehnologija.

Da bi se pokretale i JSP stranice i povezivale sa servletima potrebno ih je izvršavati na određenom Web serveru. U okviru ovog kursa koristiće se Jakarta Tomcat Web Server, na kome će se izvršavati svi primeri.

Prednosti JSP tehnologije

Odvojen statički od dinamičkog sadržaja: Kada se klijentski sadržaj generiše u okviru servleta, logika stvaranja dinamičkog sadržaja je sastavni deo koda servleta. Takođe statički deo klijentske strane je “sakrivena” u okviru servleta. Pored otežanog praćenja samog koda, nakon svake, pa i najmanje promene, servlet se mora ponovo kompajlirati. Sve ovo prouzrokuje stvaranje aplikacije čija se logika veom ateško razume, a svaka promena zahteva određeno vreme.

Sa JSP stranicama statički deo se odvaja od dinamičkog korišćenjem specialnih tagova i scriptleta. Kada dizajner strane napravi bilo koju promenu, JSP stranica se automatski rekompajlira i ponovo učita na web server pomoću JSP mašine.

Piši jednom izvršavaj bilo gde: JSP tehnologija donosi ovo pravilo i u interaktivne Web strane. JSP stranice se mogu prenositi sa jedne platforme na drugu, ili promeniti Web server, ponašanje aplikacije će biti potpuno isto.

Dinamički sadržaj se može predstaviti u različitim formatima: Ne postoji pravilo u kom formatu staitički (template) deo JSP stranice mora da bude. Tako, da JSP stranica može koristiti standardni HTML/DHTML kod koji se može izvržavati pomoću browser-a, ili WML kod koji se izvršava na hanheld bežičnim uređajima, dok novije aplikacije koriste XML kod.

Dobijanje Web pristupnog nivoa kod aplikacija n-slojnr arhitekture: Standardna Sunova dokumentacija J2EE TM Blueprints, koja predstavlja glavni vodič za implementaciju složenih Java aplikacija pomoću enterprise Java klasa i JavaBeans, kategorično preporučuje korišćenje JSP stranica u odnosu na servlete za generisanje klijentske strane aplikacije.

Potpuna usklađenost sa servlet tehnologijom: Za svakog servlet programera, potrebno je veoma malo truda i vremena za razumevanje JSP tehnolgije. U stvari, servlet programeri su u velikoj prednosti, jer je su JSP stranice u stvari servelti pisani na velikom nivou apstrakcije. Sve što se može uraditi sa servletima, može i pomoću JSP stranica, ali mnogo jednostavnije!

Arhitektura JSP stranica

Svrha postojanja JSP stranica je definisanje deklarativnog, prezentacijskog metoda za pisanje servleta. Kao što je već navedeno, JSP specifikacija je definisana kao standardna tehnologija na vrhu Servlet API klasa.

Uobičajeno je da JSP stranicaprolazi kroz dve faze: translacionu i fazu odgovra na zahtev. Translaciona faza se izvršava samo jednom, sve dok se u kod stranice ne unesu neke izmene,u kom slučaju se prevođenje ponavlja. Ako u kodu na stranici ne postoji greška, rezultat prevođenja je fajl koji predstavlja klasu implementiranu Servlet interface, kao što je prikazano na slici. Ovu fazu izvršava JSP mašina na web serveru sama, kada primi prvi put zahtev za stranicom. Takođe, JSP stranica se može iskompajlirati u class fajl pre instalacije aplikacije na server čime se izbegava kašnjenje pri prvom pozivu stranice od strane korisnika. Gde se postavlja kod stranice ili iskpmpajlirana klasa zavisi od korišćenog web servera. Kod dobijen od JSP stranice prikazane na gornjoj slici i iskompajliran od strane Tomcat serveraje sledeći:

package jsp;

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

import javax.servlet.jsp.tagext.*;

import java.io.PrintWriter;

import java.io.IOException;

import java.io.FileInputStream;

import java.io.ObjectInputStream;

import java.util.Vector;

import org.apache.jasper.runtime.*;

import java.beans.*;

import org.apache.jasper.JasperException;

import java.text.*;

import java.util.*;

public class _0005cjsp_0005cjsptest_0002ejspjsptest_jsp_0

extends HttpJspBase {

static {

}

public _0005cjsp_0005cjsptest_0002ejspjsptest_jsp_0( ) {

}

private static boolean _jspx_inited = false;

public final void _jspx_init() throws JasperException {

}

public void _jspService(HttpServletRequest request,

HttpServletResponse response)

throws IOException, ServletException {

JspFactory _jspxFactory = null;

PageContext pageContext = null;

HttpSession session = null;

ServletContext application = null;

ServletConfig config = null;

JspWriter out = null;

Object page = this;

String _value = null;

try {

if (_jspx_inited == false) {

_jspx_init();

_jspx_inited = true;

}

_jspxFactory = JspFactory.getDefaultFactory();

response.setContentType(„text/html“);

pageContext = _jspxFactory.getPageContext(this,

request,response, „“, true, 8192, true);

application = pageContext.getServletContext();

config = pageContext.getServletConfig();

session = pageContext.getSession();

out = pageContext.getOut();

// begin

out.write(„\r\n\r\n\r\n“);

// end

// begin [file=“E:\\jsp\\jsptest.jsp“;from=(3,2);to=(5,0)]

Date d = new Date();

String today = DateFormat.getDateInstance().format(d);

// end

// begin

out.write(„\r\nToday is: \r\n „);

// end

// begin [file=“E:\\jsp\\jsptest.jsp“;from=(7,8);to=(7,13)]

out.print(today);

// end

// begin

out.write(“ \r\n\r\n\r\n“);

// end

} catch (Exception ex) {

if (out.getBufferSize() != 0)

out.clear();

pageContext.handlePageException(ex);

} finally {

out.flush();

_jspxFactory.releasePageContext(pageContext);

}

}

}

Dobijena klasa od JSP stranice nasleđuje osnovnu klasu HttpJspBase, čime u stvari vrši implementaciju Servlet interfejsa.Kada se jednom klasa učita u okviru servlet container, _jspService() metod je odgovoran za odgovor na klijeske zahteve. Ovaj metod se ne može preklapati i izvršava se u posebnoj niti u okviru servlet containera. Tok izvršavanja JSP stranice je prikazan na sledećoj slici:

Modeli pristupa JSP stranicama

Rana JSP specifikacija je preporučivala dva metoda pristupa JSP stranicama, koji su nazvani Model 1 i Model 2 arhitekture. Ova dva pristupa su se razlikovala po mestu gde je vršena obrada zahteva. Model 1 arhitektura je sledeća:

Kod ovog modela, Zahtev dobijen od strane web browsera se šalje direktno JSP stranici, koj aje odgovorna za procesiranje zahteva i generisanje odgovora klijentu. Još uvek postoji razdvajanje klijentskog od sreverskog dela aplikacije, jer se svi pristupi podacima odvijaju preko Java Beans. Model 1 arhitektura se može koristiti za jednostavnije aplikacije, dok je za kompleksne implementacije ovaj model nepogodan. Korišćenje ove arhitekture obično dovodi do veoma velike količine scriptleta Java koda u okviru JSP stranice, posebno u slučajevima kada postoji složenije obrada klijetnskih zahteva. Na ovaj način se gubi mogućnost da i dizajneri učestvuju u razvoju logike strane, jer je za ovu vrstu implementacije potrebno veće Java iskustvo. Još jedan nedostatak ovakve arhitekture je da svaka JSP stranica stranica mora individualno da vodi računa o stanju aplikacije.

Arhitektura Modela 2 je sledeća:

Osnovna sintaksa JSP stranica

JSP sintaksu možemo grubo podeliti na direktive, scripting elemente, i standardne akcije.

Direktive

JSP direktive su poruke za JSP mašinu. One ne proizvode nikakav vidljivi izlaz, ali govore mašini šta da radi sa ostatkom JSP stranice. JSP direktive se nalaze u okviru taga. Dve osnovne direktive su page and include. (Postoji još i taglib direktiva, koja se može koristiti za rad sa tag bibliotekama, ali neće biti razmatrana u daljem tekstu.)

Page Direktiva

Uobičajeno je da se ova direktiva nalazi u vrhu svih JSP stranica. Može se navseti proizvoljan broj page direktiva u okviru jedne JSP stranice, ali vrednost u okviru taga mora biti jedinstvena. Nepoznati atributi ili vrednosti dovode do greške pri kompajliranju. Na primer,

dozvoljava korišćenje svih klasa koje postoje u okviru navedenih paketa u okviru scripting elemenata u nastavku stranice, kao i setovanje bafera stranice na 16K.

Include Direktiva

include direktiva daje mogućnost podele sadržahja stranice u manje, lakše razumljive elemente, kao što su uključivanje u svaku stranicu aplikacije standardnih headera ili footer-a. Stranica koja se poziva u okviru ove direktive može biti statička HTML strana ili neki drugi JSP sadržaj. Na primer direktiva:

se može koristiti za prikaz sadržaja fajla copyright.html bilo gde u okviru JSP stranice.

Deklaracije

JSP deklaracije dozvoljavaju definisanje promenljivih na nivou stranice radi snimanja određenih informacija ili definisanja određenih metoda koji su potrebni ostatku JSP stranice. Takođe, na ovaj način se mogu koristiti i JavaBeans komponente. Deklaracija se piše u okviru taga. Uvek se deklaracija promenljivih završava tačka zarezom i njen sadržaj mora biti validna Java naredba. Primer deklaracije promenljive:

Takođe mogu se deklarisati i methodi. Na primer preklapanje osnovnog metoda za inicijalizaciju događaja u okviru života JSP stranice se deklariše na sledeći način:

<%!public void jspInit(){

//some initialization code

}

%>

Izrazi

Kada JSP mašina naiđe na izraz u okviru stranice, izračunava se rezultat izraza, konvertuje u string i direktno prikazuje na izlaznom dokumentu. Obično, izrazi se koriste za prikazivanje vrednosti promenljivih ili vrednosti dobijene nakon izvršavanja pozvane JavaBeans komponente. JSP izrazi se nalaze u okviru taga i ne završavaju se tačka zarezom:

Scriptleti

Java kod u okviru JSP strane ili scriptleti se nalaze u okviru taga. Ovaj Java kod se izvršava pri obradi zahteva od JSP stranice. U okviru scripleta se može pisati bilo koji validan Java kod i količina koda nije limitirana na jednu liniju. Sledeći primer prikazuje string „Zdravo“ pomoću H1, H2, H3, i H4 taga, combinujući korišćenje izraza i scriptleta:

<% for (int i=1; i

<H>Hello</H>

Komentari

Iako se mogu koristiti standardni HTML komentari u okviru JSP stranice, ove komentare klijent može da vidi ako pogleda kod dobijen u okviru browser-a. Ako se to ne želi, mogu se koristiti komentari u okviru taga:

Oblast važenja promenljivih

Predefinisani JSP Objekti

Kao dodatna prednost tehnologije, JSP container dozvoljava korišćenje predefinisanih objekata, koji se mogu koristiti u okviru scriptleta i izraza, bez potrebe da ih autor prvo kreira pre upotrebe. Ovi objekti su:

• request: predstavlja objekat tipa HttpServletRequest. Oblast važenja je u okviru zahteva.

• response: predstavlja objekat tipa HttpServletResponse za zahtev. Ne koristi se često. Oblast važenja je u okviru stranice.

• pageContext: obuhvata osobine u zavisnosti od implementacije u okviru PageContext objekta. Oblast važenja je u okviru stranice.

• application: predstvalja objekat tipa ServletContext. Oblast važenja je u okviru aplikacije.

• out: predstavlja objekat tipa JspWriter koji zapisuje podatke u izlazni stream. Oblast važenja je u okviru stranice..

• config: predstvalja ServletConfig objekat za JSP stranicu. Oblast važenja je u okviru stranice.

• page: sinonim za „this“ operator, to jest za HttpJspPage.objekat. Ne koristi se često. Oblast važenja je u okviru stranice.

• session: objekat tipa HttpSession. Oblast važenja je u okviru sesije.

• exception: objekat tipa Throwable čije izvršavanje rezultuje pozivanjem error stranice koja je definisana u okviru ovog objekta. Oblast važenja je u okviru stranice.

Neki od navedenih metoda su vidljivi samo u okviru _jspService() metoda. Oni nisu vidljivi autoru i ne mogu se koristiti u deklaracijama.

Mogućnosti sihronizacije

Po definiciji service metod JSP stranice implementiran u prevedenu klasu, koji opslužuje zahteve klijenta je višekorisnički (multithreaded). Na ovaj način, odgvoronost je programera da li je pristup deljenim stanjima dobro sihronizovan. Postoji nekoliko načina da se obezbedi da service method bude bezbedan po pitanju sihronizacije. Najlakši način je pomoći sledeće direktive:

Ova direktiva prouzrokuje da se izvrši implementacija SingleThreadModel interface, čiji rezultat je sihronizacija, i više instanci servleta se učitava u memoriju Paralelni zahtevi više klijenata se distribuiraju između ovih instanci. Ovaj metod ne daje najbolje perfomanse. Bolji način je eksplicitni sinhroni pristup deljenim objektima pomoću Java koda u okviru scriptleta:

<%

synchronized (application) {

SharedObject foo = (SharedObject)

application.getAttribute(„sharedObject“);

foo.update(someValue);

application.setAttribute(„sharedObject“,foo);

}

%>

Rukovođenje izuzecima

JSP tehnologija omogućava elegantan mehanizam za handlovanje runtime exception. Korišćenjem atributa errorPage au okviru page direktive, moguće je u slučaju nepredviđene greške usmeriti program na izvršavanje stranice za obradu greške. Na primer,

informiše JSP mašinu d au slučaju bilo kakve neočekivane greške aplikaciju nastavi izvršavanjem JSP stranice errorHandler.jsp. Takođe, neophodno je u okviru errorHandler.jsp tstranice naznačiti da se radi o stranici koja je pozvana, jer se desila greška, pomoću direktive:

Rad sa sesijom

Po definiciji, sve JSP stranice se izvršavaju u okviru HTTP sesije. Objektu HttpSession može se pristupiti iz Java koda implicitnim navođenjem session JSP objekta. Sesije su odlične lokacije za smeštanje objekata kojima je potrebno pristupati iz nekoliko JSP stranica ili servleta. Objekat session se identifikuje preko session ID i zapisan je u okviru browser-a kao cookie. Ako cookies nisu podržani od strane browser-a, tada se session ID može pamtiti pomoću samog URL, ali je ova mogućnost podržana samo kod nekoliko web servera:

<%

Foo foo = new Foo();

session.putValue(„foo“,foo);

%>

omogućava pristup Foo instanci preko svih JSP stranica i servleta koji pripadaju istoj sesiji. Instanci ovog objekta se može pristupiti sa druge JSP stranice preko sledećeg koda:

<%

Foo myFoo = (Foo) session.getValue(„foo“);

%>

Poziv session.getValue() vraća referencu na osnovni Object tip. Zato je veoma važno navesti kog tipa je promenljiva koja je pročitana, pre njenogkorišćenja. Moguće je definisati da određena JSP stranica ne pripada sesiji pomoću određenog atributa u okviru page direktive:

Ne postoji limitiran broj koliko se objekata može zapamtiti u okviru sesije. Treba napomenuti da smeštanje velikih objekata u sesiju može bitno da degradira perfomanse aplikacije. Po definiciji većina servera setuje vreme objekta sesije na 30 minuta, ali se može jednostavno resetovati i menjati pozivom metoda invoking setMaxInvalidationInterval(int secs) nad objektom sesije. Naredna slika opisuje način rukovođenja sesijom:

JSP mašina održava reference na objekte smeštene u sesiji onoliko dugo koliko je sesija validna. Ako sesija postaje nevalidna ili istekne vreme sesije, objecti sesije se označavaju za garbage collection.

Hidden promenljive

Organizacija Web Aplikacije

Jedna od mogućnosti je distribucija Web aplikacije u obliku fajla Web ARchive, ili WAR fajla, koji predstvalja standardni format za većinu servera.

Prvi i osnovni direktorijum se naziva document root aplikacije. Tu se smeštaju HTML fajlovi i JSP stranice, to jest klijentski deo aplikacije.Kada se aplikacija instalira na sistem definiše se putanja do aplikacije. Na primer ako je definisana putanja /catalog, tada pozivni URI glasi /catalog/index.html i izvršavaće se index.html sa document roota aplikacije.

Standardni Direktorijumi

• *.html, *.jsp, itd. – HTML i JSP stranice, zajedno sa ostalim fajlovima koji se koriste na kloijetskoj strani (kao što su JavaScript i stylesheet fajlovi) se smeštaju u osnovni direktorijum. Kod većih aplikacija može se napraviti poddirektorijumi i ova hijerarhija.

• WEB-INF/web.xml – Web Application Deployment Descriptor Ovo je XML fajl koji opisuje servlete i druge komponente koji čine aplikaciju, zajedno sa bilo kojim inicijalizacionim parametrima i različitim oblicima zaštite.

• WEB-INF/classes/ – U ovaj direktorijum se smeštaju sve Java klase koje se koriste u aplikaciji, uključujući i sevlet i ne-servlet klase.

• WEB-INF/lib/ – U ovaj direktorijum se smeštaju svi JAR fajlovi potrebni za izvršavanje aplikacije (kao što su na primer JDBC dajveri).

JDBC

JDBC je JAVA API za baze podataka bazirane na SQL jeziku. JDBC je predstavljen u obliku na nivou poziva SQL interface za Javu. Znači, pomoću klasa iz ovog paketa se mogu izvršavati SQL naredbe i manipulisati sa rezultatima dobijenim na osnovu ovih naredbi.

JDBC API sadrži niz abstraktnih Java interface koji dozvoljavaju programeru da ostvari konekciju sa određenom bazom podataka, izvrši SQL naredbe i obradi dobijene rezultate.

Najvažniji interface u okviru ovog paketa su:

– java.sql.DriverManager sprovodi učitavanje driver-a baze podataka i omogućava podršku za kreiranje nove konekcije

– java.sql.Connection predstavlja konekciju sa određenom bazom podataka

– java.sql.Statement izvrašava se u obliku container-a za izvršavanje SQL naredbi u okviru uspostavljene konekcije

– java.sql.ResultSet kontroliše pristup rezultatima dobijenim izvršavanjem određene SQL naredbe

java.sql.Statement interface ima dva važna podtipa:

– java.sql.PreparedStatement za izvršavanje pre-kompajlirane SQL neredbe i

– java.sql.CallableStatement za izvršavanje poziva stored procedura koje postoje u okviru baze podataka.

JDBC URL ima sledeću strukturu: jdbc:: gde je subprotocol ime odrđene vrste mehanizma pristupa bazi podataka koji može biti podržan od jednog ili više drajvera. Sadržaj i sintaksa dela subname zavisi od subprotocola.

JDBC management nivo mora da zna koji drajver je raspoloživ i koji drajver se koristi..

Primer inicijalizacije drajvera baze podataka:

Class.forName(„sun.jdbc.odbc.JdbcOdbcDriver“);

Class.forName(„org.gjt.mm.mysql.Driver”);

Example: Execute Query

import java.sql.*;

public class JDBCDemoCreateTable {

public static void main(String[] args) {

// 1. step loading the driver

try {

Class.forName(„sun.jdbc.odbc.JdbcOdbcDriver“);

// 2. step making the connection

String url = „jdbc:odbc:BootCamp“ ;

String myLogin = „mika“ ; // the name you use to log in to the DBMS

String myPassword = „mika“ ; // your password for the DBMS

try {

Connection con = DriverManager.getConnection( url, myLogin, myPassword );

String createTableCoffees = „CREATE TABLE COFFEES “ +

„(COF_NAME VARCHAR(32), SUP_ID INTEGER, PRICE FLOAT, “ +

„SALES INTEGER, TOTAL INTEGER)“;

// 3. step creating JDBC sStatement. A Statement object is what sends your SQL

// statement to the DBMS. You simply create a Statement object and then execute

// it, supplying the appropriate execute method with the SQL statement you want

// to send. For a SELECT statement, the method to use is executeQuery . For

// statements that create or modify tables, the method to use is executeUpdate

Statement stmt = con.createStatement();

stmt.executeUpdate(createTableCoffees);

} catch ( SQLException e ) { System.err.println( e ); }

}catch ( ClassNotFoundException e) { System.out.println(„Error : “ + e ); }

}

}—-

import java.sql.*;

public class JDBCDemoUpdateTable {

public static void main(String[] args) {

try {

Class.forName(„sun.jdbc.odbc.JdbcOdbcDriver“);

try {

Connection con = DriverManager.getConnection( „jdbc:odbc:BootCamp“, „mika“, „mika“ );

Statement stmt = con.createStatement();

String updateTableCoffees = „INSERT INTO COFFEES VALUES (‘Colombian’, 101, 7.99, 0, 0)“ ;

stmt.executeUpdate( updateTableCoffees );

updateTableCoffees = „INSERT INTO COFFEES VALUES (‘French_Roast’, 49, 8.99, 0, 0)“ ;

stmt.executeUpdate( updateTableCoffees );

updateTableCoffees = „INSERT INTO COFFEES VALUES (‘Espresso’, 150, 9.99, 0, 0)“ ;

stmt.executeUpdate( updateTableCoffees );

updateTableCoffees = „INSERT INTO COFFEES VALUES (‘Colombian_Decaf’, 101, 8.99, 0, 0)“ ;

stmt.executeUpdate( updateTableCoffees );

updateTableCoffees = „INSERT INTO COFFEES VALUES (‘French_Roast_Decaf’, 49, 9.99, 0, 0)“ ;

stmt.executeUpdate( updateTableCoffees );

} catch ( SQLException e ) { System.err.println( e ); }

}catch ( ClassNotFoundException e) { System.out.println(„Error : “ + e ); }

}

}—

import java.sql.*;

public class JDBCDemoSelectTable {

public static void main(String[] args) {

try {

Class.forName(„sun.jdbc.odbc.JdbcOdbcDriver“);

try {

Connection con = DriverManager.getConnection( „jdbc:odbc:BootCamp“, „mika“, „mika“ );

Statement stmt = con.createStatement();

String queryTableCoffees = „SELECT COF_NAME, SUP_ID, PRICE, SALES, TOTAL FROM COFFEES“ ;

// JDBC returns results in a ResultSet object, so we need to declare an instance of the

// class ResultSet to hold our results. The following code demonstrates declaring the

// ResultSet object rs and assigning the results of our earlier query to it:

ResultSet rs = stmt.executeQuery( queryTableCoffees );

while (rs.next()) {

String coffeName = rs.getString(„COF_NAME“);

int supplierId = rs.getInt(„SUP_ID“);

float price = rs.getFloat(„PRICE“);

int sales = rs.getInt( 4 );

int total = rs.getInt( 5 );

// JDBC allows you to use either the column name or the column number as the argument to a getXXX method

System.out.println( coffeName + “ “ + supplierId + “ “ + price + “ “ +

sales + “ “ + total );

}

} catch ( SQLException e ) { System.err.println( e ); }

} catch ( ClassNotFoundException e) { System.out.println(„Error : “ + e ); }

}

}—

Example: Using parameter Query

/**

*

* If you want to execute a Statement object many times, it will normally reduce

* execution time to use a PreparedStatement object instead.

*

*/

import java.sql.*;

public class JDBCDemoPreparedStatement {

public static void main(String[] args) {

try {

Class.forName(„sun.jdbc.odbc.JdbcOdbcDriver“);

try {

Connection con = DriverManager.getConnection( „jdbc:odbc:BootCamp“, „mika“, „mika“ );

PreparedStatement updateSalesPrepared = con.prepareStatement( „UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?“);

int [] salesForWeek = {175, 150, 60, 155, 90};

String [] coffees = {„Colombian“, „French_Roast“, „Espresso“,

„Colombian_Decaf“, „French_Roast_Decaf“};

int len = coffees.length;

for(int i = 0; i < len; i++) {

updateSalesPrepared.setInt(1, salesForWeek[i]); // setting up first parameter

updateSalesPrepared.setString(2, coffees[i]); // setting up second parameter

updateSalesPrepared.executeUpdate(); // executing update

}

Statement stmt = con.createStatement();

String queryTableCoffees = „SELECT COF_NAME, SALES FROM COFFEES“ ;

ResultSet rs = stmt.executeQuery( queryTableCoffees );

while (rs.next()) {

String coffeName = rs.getString(„COF_NAME“);

int sales = rs.getInt(2);

System.out.println( coffeName + “ “ + sales );

}

} catch ( SQLException e ) { System.err.println( e ); }

} catch ( ClassNotFoundException e) { System.out.println(„Error : “ + e ); }

}

}

Example: Using CallableStatement

import java.sql.*;

public class JDBCDemoCallableStatement {

public static void main(String[] args) {

try {

Class.forName(„sun.jdbc.odbc.JdbcOdbcDriver“);

String url = „jdbc:odbc:BootCamp“ ;

String myLogin = „mika“ ; // the name you use to log in to the DBMS

String myPassword = „mika“ ; // your password for the DBMS

try {

Connection con = DriverManager.getConnection( url, myLogin, myPassword );

// A stored procedure is a group of SQL statements that form a logical unit and perform a particular task

String createProcedure = „create procedure SHOW_SUPPLIERS “ +

„as “ +

„select SUPPLIERS.SUP_NAME, COFFEES.COF_NAME “ +

„from SUPPLIERS, COFFEES “ +

„where SUPPLIERS.SUP_ID = COFFEES.SUP_ID “ +

„order by SUP_NAME“;

Statement stmt = con.createStatement();

stmt.executeUpdate(createProcedure);

// Calling a Stored Procedure from JDBC

CallableStatement cs = con.prepareCall(„{call SHOW_SUPPLIERS}“);

ResultSet rs = cs.executeQuery();

while (rs.next()) {

String supName = rs.getString(„SUP_NAME“);

String coffyName = rs.getString(„COF_NAME“);

System.out.println( supName + “ “ + coffyName );

}

}catch ( SQLException e ) { System.err.println( e ); }

} catch ( ClassNotFoundException e) { System.out.println(„Error : “ + e ); }

}

}

Mapping SQL data types into Java and Use of ResultSet.getXXX Methods to Retrieve JDBC Types

SQL type TINYINT SMALLINT INTEGER BIGINT REAL FLOAT DOUBLE DECIMAL NUMERIC BIT CHAR VARCHAR LONGVARCHAR BINARY VARBINARY LONGVARBINARY DATE TIME TIMESTAMP

Java Type String String String java.math.BigDecimal java.math.BigDecimal boolean byte short int long float double double byte[] byte[] byte[] java.sql.Date java.sql.Time java.sql.Timestamp

getByte X x x x x x x x x x x x x

getShort x X x x x x x x x x x x x

getInt x x X x x x x x x x x x x

getLong x x x X x x x x x x x x x

getFloat x x x x X x x x x x x x x

getDouble x x x x x X X x x x x x x

getBigDecimal x x x x x x x X X x x x x

getBoolean x x x x x x x x x X x x x

getString x x x x x x x x x x X X x x x x x x x

getBytes X X x

getDate x x x X x

getTime x x x X x

getTimestamp x x x x x X

getAsciiStream x x X x x x

getUnicodeStream x x X x x x

getBinaryStream x x X

getObject x x x x x x x x x x x x x x x x x x x

An „x“ indicates that the getXXX method may legally be used to retrieve the given JDBC type.

An “ X “ indicates that the getXXX method is recommended for retrieving the given JDBC type.

Relationships between the interface

prvi java aplet

Prvi JAVA aplet

Applet ZdravoAplet

Jedan od razloga popularnosti Jave je mogućnost pisanja interaktivnih apleta na Web-u. Naredni aplet nije baš interaktivan, jer je primer jednostavnog apleta koji ispisuje tekst poruke u HTML dokument:

import java.applet.Applet;

import java.awt.Graphics

public class ZdravoAplet extends Applet {

public void paint(Graphics g) {

g.drawString(„Zdravo, svete!“, 5, 50);}

}

Aplet ZdravoAplet jeste malo kompleksniji u odnosu na aplikaciju ZdravoSvete. Zatim, potrebno je i više posla pri pokretanju.

Kao i pri izradi aplikacije urade se dva koraka: unos izvornog koda u editor i čuvanje u datoteci ZdravoSvete.java i kompilacija.

Rezultat je klasa ZdravoAplet.class. Za potrebe njenog pokretanja kreira se HTML dokument koji će sadržati aplet, npr.datoteka (ZdravoAplet.html)

Zdravo aplet

Jednostavnosti radi, neka se datoteka datoteka ZdravoAplet.html i datoteka datoteka ZdravoAplet.class nalaze u istom direktorijumu.

HTML datoteka se može pregledati pomoću Java enabled browsera kao što je Internet Explorer, Netscape ili Applet viewer koji se nalazi u JDK paketu.

Vidi se string Zdravo, svete ! unutar pravougaonika veličine 400×400 pixel-a.

Ako je kompilacija prošla bez greške, a ne vidi se string Zdravo, svete !, onda:

1. proveriti da li klasa je u istom direktoriju kao i HTML datoteka

2. proveriti da li koristete verziju navigatora koja podržava Javu.

3. ako ni appletviewer ne vidi aplet, proveriti aplet, pa potom kompatiblnost navigator-a

Razvojni put apleta

Applet je mala aplikacija koja je zamišljena da se ne izvršava samostalno, nego unutar druge aplikacije, tnpr. unutar web browsera. Klasa java.applet.Applet osigurava standardnu sumedju izmedju apleta i njihove okoline. Evo što se sve naziva appletom:

mala aplikacija

sigurni program koji se izvršava unutar web browsera

podklasa klase java.applet.Applet

instanca podklase od java.applet.Applet

Ovo je hijerarhija njenih nadklasa:

java.lang.Object

|

+—java.awt.Component

|

+—java.awt.Container

|

+—java.awt.Panel

|

+—java.applet.Applet

HTML oznaka

Appleti se u HTML kod ugrađuju pomoću oznake i . Oznaka se ponaša na Web strani poput oznake . Kompajlirana klasa koja sadrži kod apleta kod referencira se pomocu atributa CODE, a lokacija se zadaje relativno u odnosu na izvorni HTML dokument.

Na primer, ako je URL HTML dokumenta http://www.nesto.com/java/index.html, i ako se u HTML kodu applet referiše sa CODE=“Nesto.class“, onda URL datoteke Nesto.class je http://www.nesto.com/java/Nesto.class.

Ali, ako se aplet ne nalazi u istom direktoriju kao i HTML dokument, ne može se u atributu

java appleti

Postoje dve kategorije JAVA programa:
1. Java apleti (applets)
2. Java aplikacije

Java apleti su programi ugrađeni u HTML dokumente koji se izvršavaju u lokalnom Web navigatoru. Za njihovo izvršavanje neophodno je da navigator poseduje ugrađene JAVA sposobnosti, ali se mogu pogledati i pomoću alata zvanog appletviewer koji dolazi u okviru JDK .
Java aplikacije ne zahtevaju navigator da bi se pokrenuli, a neki Java program može biti aplet ili aplikacija ili jedno i drugo u zavisnosti od funkcionalnosti koja je ugrađena u program.

Primer 1: Java aplikacija za primer ispisa niske Zdravo, svete na standardni izlaz.

class ZdravoSvete {
public static void main (String args[])
{
System.out.println(„Zdravo, svete“);
}
}

Postoje dva suštinska dela ovog programa:
definicija: kompletan program je zatvoren u definiciju klase koja se ovde zove ZdravoSvete
telo programa: kao i u C/C++ funkcija main( ) je prva funkcija koja se izvršava po startovanju programa.
1. Nakon što je program unet u editor (ma koji editor), izvorna datoteka se čuva sa ekstenzjom .java
2. Praksa je da se izvornom kodu daje ime klase koja je u njemu definisana, dakle datoteku nazovite ZdravoSvete.java
3. Kompajlirajte datoteku javac kompajlerom, tj. u komandnoj liniji otkucajte
javac ZdravoSvete.java
4. Kompajler će kao izlaz dati fajl istog imena sa ekstenzijom .class (ekstenzija izvršnih Java programa)
5. Pokrenite program java interpreterom, tj. u komandnoj liniji otkucajte
java ZdravoSvete

Dakle, postoje tri suštinska koraka u stvaranju/izvršavanju programa:
1. pisanje kôda
2. kompilacija izvornog kôda
3. pokretanje kompajliranog kôda

Pod UNIXom kompilacija i izvršavanje izgleda ovako:

javac ZdravoSvete.java
java ZdravoSvete
Zdravo, svete

Ako se na računaru Java kompajler (javac), Java interpreter (java) i ostali alati nalaze u direktoriju /nesto/java/bin, onda dodati putanju direktorijuma u $PATH promenljivu:
% export PATH=$PATH:/nesto/java/bin

Pod Windows-om mora se koristiti DOS-shell pri upotrebi JDK:

C:> javac ZdravoSvete.java
C:> java ZdravoSvete
Zdravo, svete
C:>

Pri tom se podesi vrednost promenljive PATH tako da sadrži adekvatni direktorijum gde je instaliran jdk, npr . . .;c:\nesto\jdk1.4.0_02\bin\; . . . (definisana u odgovarajućoj liniji datoteke autoexec.bat ili se podesi vrednost putem
Start => Settings => System=> Environment Variables => PATH )

/******Primetite upotrebu .java ekstenzije kod kompajliranja, ali ne i .class ekstenzije kod izvršavanja!!!***********/

Preporuke pri izradi Java programa

1. Fajlovi koji sadrže izvorni kod nazvati po definisanim klasama unutar fajla, jer kompajler će kao izlaz dati fajl sa ekstenzijom .class i imenom klase koja je u fajlu definisana, te nije zgodno da nazivi datoteka sa izvornim i izvršivim kodom budu različiti.
2. Zgodno je definisati jednu klasu u jednom fajlu, jer kompajler svaku prevedenu klasu smešta u poseban .class fajl, te je moguće od jedne izvorne datoteke dobiti više .class fajlova što može biti neudobno za celokupnu organizaciju na disku.
3. Java interpreter java je osetljiv na veličinu slova (case sensirive) u nazivu datoteka.
4. Pri interpretiranju ne kucati ekstenziju .class iza naziva programa, jer zbog interne koncepcije jezika tačka može biti protumačena kao deo puta do izvršive verzije.

Ispis na standardni izlaz

U prethodnoj aplikaciji za ispis poruke Zdravo, svete na standardni izlaz je upotrebljen metod println, tj. System.out.println(„Zdravo, svete“);

Za ispis linije koristi se metod println(…) iz klase PrintStream. U našem prvom Java programu
System.out.println() ispisuje sadržaj toka standardnog izlaza System.out
klase System, u ovom slučaju tekst poruke iza kog sledi separator linije. Zavisno od platforme to moze biti:
carriage return(ASCII 13, \r) i linefeed (ASCII 10, \n) na DOS/Windows
linefeed na UNIX
carriage return na Mac-u

System.err.println(…) ispisuje sadržaj na standardni tok za poruke o grešci System.err.

Moguće je konkatenirati niske koje su argumenti metode println() pomoću znaka +, npr.
System.out.println(„Ucitano je “ + args.length + „argumenata s komandne linije“);
gde args.length predstavlja broj argumenata komandne linije.

Ako se koristi print(…) umesto println(), onda nema znaka za prelaz u novi red nakon ispisa, 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, te se ništa neće ispisati na ekranu
dok god se ne pojavi znak prelaza u novi red.

Klasa ZdravoSvete

Program u Java-i predstavlja klasu. Svaka klasa ima ime koje, po konvenciji, počinje velikim slovom, npr.
class ZdravoSvete
Prva linija aplikacije našeg primer glasi
public static void main (String args[])
Aplikacije u Java-i iamju f-ju main od koje i počinje izvršavanje.
public čini aplikaciju javnom (dostupnom spolja), tj. iz konzole.
Java program se sastoji iz niza naredbi unutar bloka omeđenog vitičastim zagradama. U našem primeru to je metod println.

main (String args[])
pod imenom args definiše niz stringova koji su parametri komandne linije. Niz args[] sakuplja sav tekst komandne linije otkucan iza imena programa i kad se pokrene program, onda args[0] sadrži prvi string komandne linije, …, jer ime klase nije uključeno u listu argumenata.
Argumenti komandne linije se, dakle, mogu preneti u program i to kao niz stringova args. Početni indeks svakog niz je nula kao u C/C++. Npr, ako tekst komandne linije glasi
java stampaj Zdravo Pero
onda args[0] je string „Zdravo“, args[1] je string „Pero“, dok args.length je 2.

Svi argumenti komandne linije prenose se kao stringovi, nikad kao brojevi. Kasnije će prikazati konverzija stringova u brojeve.

U Java-i postoje dve klase za rad sa tekstom i njegovo pohranjivanje: String, StringBuffer.

Razvijni put aplikacije

Obrada izuzetaka

Obrada izuzetaka

Izuzeci su mehanizam za kontrolu toka programa koji se koristi za obradu grešaka nastalih u toku izvršavanja programa. Segment programskog koda za koji smatramo da može da izazove izuzetak možemo da smestimo u tzv. try/catch blok, kao u sledećem primeru:

try {

// kod koji može da izazove izuzetak

} catch (Exception ex) {

System.out.println(„Desio se izuzetak: “ + ex);

}

Izuzetak može biti, na primer, deljenje nulom, pristup elementu niza koji je izvan granice niza, itd. Ukoliko se prilikom izvršavanja koda koji se nalazi u try bloku desi izuzetak, tok izvršavanja programa se automatski prebacuje na početak catch bloka. Nakon izvršavanja koda u catch bloku, program dalje nastavlja rad.

U okviru catch bloka, informacije o samom izuzetku koji se dogodio su dostupne preko objekta klase Exception ili neke njene naslednice. U primeru je to objekat ex.

Različite vrste izuzetaka su predstavljene različitim exception klasama, na primer: svi izuzeci prilikom izvršavanja aritmetičkih operacija (deljenje nulom, overflow itd.) su predstavljeni klasom Arithmetic Exception; pristup elementu čiji je indeks izvan granice niza je predstavljen klasom ArraylndexOutOfBounds-Exception itd. Klasa Exception je zajednički predak svim exception klasama.

Jedan try blok može imati više sebi pridruženih catch blokova, kao u sledećem primeru:

try {

// kod koji može da izazove izuzetak

}

catch (ArithmeticException ex) {

System.out.println(„Deljenje nulom“);

}

catch (ArrayIndexOutOfBoundsException ex) {

System.out.println(„Pristup van granica niza“);

}

catch (Exception ex) {

System.out.println(„Svi ostali izuzeci“);

}

finally {

// kod koji se izvršava u svakom slučaju

}

Kada se dogodi izuzetak, niz catch blokova se sekvencijalno obilazi i ulazi se u onaj catch blok čija klasa odgovara izuzetku koji se dogodio. Reč odgovara u ovom slučaju znači: u pitanju je klasa kojoj exception objekat pripada ili njen predak. Kada poslednji catch blok hvata izuzetak klase Exception, to znači da će svi izuzeci biti obrađeni, jer je klasa Exception zajednički roditelj. Blok finally se ne mora navesti. On sadrži blok koda koji će se izvršiti u svakom slučaju, desio se izuzetak ili ne.

Kao što postoje odgovarajuće klase koje opisuju različite vrste izuzetaka, moguće je definisati i nove vrste izuzetaka definicijom odgovarajuće klase. Na primer, možemo da definišemo novu vrstu izuzetka predstavljenog klasom MojException, koja je data u primeru:

public class MojException extends Exception {

public MojException() {

super();

}

public MojException (String msg) {

super(msg);

}

}

Klasa MojException ima dva konstruktora koji pozivaju odgovarajuće konstruktore roditeljske klase Exception. Pisanje ovakvih konstruktora nije obavezno, ali je obavezno naslediti klasu Exception (ili nekog njenog potomka).

Dosad ste samo hvatali izuzetke koje je bacao Javin izvršni sistem. Međutim, vaš program može i izričito da baci određeni izuzetak pomoću naredbe throw. Ovakav korisnički izuzetak može biti izazvan samo programski, pomoću ključne reči throw, kao u sledećem primeru:

If (errorCheck())

throw new MojException („Houston, we have a problem.“);

Programski kôd koji sadrži ovakvu throw naredbu mora biti smešten unutar try bloka koji hvata izuzetak MojException – na to će nas naterati kompajler. Dakle, ovo bi moglo da izgleda na sledeći način:

try {

if(errorCheck())

throw new MojException(„Houston, we have a problem.“);

} catch (MojException ex) {

System. out. println( „Exception: “ + ex);

}

}

Drugi način da obradimo nastanak ovakvog izuzetka je da metodu u kojoj se nalazi throw naredba označimo kao metodu u kojoj može da nastane izuzetak date vrste. Na primer:

public void metoda() throws MojException {

if (errorCheck())

throw new MojException(„Houston, we have a problem.“);

}

Sada poziv ovakve metode mora biti u odgovarajućem try bloku ili metoda koja sadrži ovaj poziv mora isto biti označena da može da izazove izuzetak. Dakle:

public void ml() {

try {

metoda ();

} catch (MojException ex) {

System. out. println („Exception: “ + ex);

}

}

ili

public void ml() throws MojException {

metoda();

}

Pogledajmo sledeći primer koji pravi sopstvenu klasu za obradu izuzetka:

class KlasaIzuzetak extends Exception {

private int iz;

KlasaIzuzetak(int a) {

iz = a;

}

public String toString() {

return „Klasa izuzetak[“ + iz + „]“;

}

}

class GlavniSopstvena{

static void Obradi(int a) throws KlasaIzuzetak {

System.out.println(„Pozvana obrada(“ + a + „)“);

if(a > 10)

throw new KlasaIzuzetak(a);

System.out.println(„Normalan izlazak“);

}

public static void main(String args[]) {

try {

Obradi(1);

Obradi(20);

} catch (KlasaIzuzetak e) {

System.out.println(„Uhvacen: “ + e);

}

}

}

Rezultat ovog programa je:

Pozvana obrada(1)
Normalan izlazak
Pozvana obrada(2)
Uhvacen: Klasa izuzetak[20]

Polimorfizam i redefinisanje metoda

Polimorfizam i redefinisanje metoda

Redefinisanje metoda omogućava polimorfizam u trenutku izvršavanja. Polimorfizam omogućava da opšta klasa definiše metode koje će biti zajedničke za sve klase koje su iz nje izvedene, ostavljajući potklasama slobodu da definišu specifične varijante nekih ili svih pomenutih metoda. Posmatrajmo sledeće tri klase:

class Instrument {

abstract void sviraj();

}

class Violina extends Instrument {

void sviraj() {…}

}

class Klarinet extends Instrument {

void sviraj () {…}

}

Class Muzicar {

void sviraj (Instrument i) {

i . sviraj ();

}

}

Kada metoda potklase ima isto ime i tip kao neka metoda natklase, tada metoda potklase ima prednost nad metodom natklase, ona je redefiniše (engl. override). Kada se unutar potklase pozove tako redefinisana metoda, uvek će se izvršiti njena verzija koja je definisana u potklasi. Verzija metode koja je definisana u natklasi će biti skrivena.

Dakle, prethodni primer definiše tri klase: klasa Instrument je apstraktna klasa (njena metoda sviraj je apstraktna), a klase Violina i Klarinet nasleđuju klasu Instrument i, naravno, implementiraju (redefinišu) apstraktnu metodu. Posmatrajmo sada klasu Muzicar:

Class Muzicar {

void sviraj (Instrument i) {

i . sviraj ();

}

}

Vidimo da klasa Muzičar ima metodu sviraj, koja kao parametar ima instancu klase Instrument; sa druge strane, znamo da klasa Instrument ne može imati instance jer je apstraktna.

Metoda sviraj će ipak biti upotrebljiva, jer se njoj kao parametar može proslediti instanca neke klase koja nasleđuje klasu Instrument, u ovom slučaju – instance klasa Violina i Klarinet. Iskaz:

Muzicar m = new Muzicar();

m.sviraj (new Klarinet());

izazvaće pozivanje metode sviraj klase Klarinet (iako se to nigde eksplicitno ne navodi u metodi sviraj klase Muzicar). Iskaz:

m. sviraj (new Violina());

izazvaće pozivanje metode sviraj klase Violina po istom principu. Dakle, poziv metode sviraj klase Muzicar će imati različite efekte zavisno od toga koji objekat prosledimo kao parametar. Određivanje koja metoda će se pozvati obavlja se u toku izvršavanja programa.

Pogledajmo sledeći primer:

class A {

int i, j;

A(int a, int b) {

i = a;

j = b;

}

void show() {

System.out.println(„i and j: “ + i + “ “ + j);

}

}

class B extends A {

int k;

B(int a, int b, int c) {

super(a, b);

k = c;

}

// Prikazuje k – ovim se redefinise metoda show() u A

void show() {

System.out.println(„k: “ + k);

}

}

class Override {

public static void main(String args[]) {

B subOb = new B(1, 2, 3);

subOb.show(); // poziva metodu show() u B

}

}

Rezultat programa će biti:

k: 3.

Ukoliko se želi izbeći redefinisanje metoda, tada se koristi rezervisana reč final. Već je bilo reči da final služi za pravljenje konstanti, međutim, ona se odnosi i na nasleđivanje. Da bi onemogućili redefinisanje određene metode, na početak njene deklaracije se stavlja modifikator final. Metode koje su označene kao final se ne mogu redefinisati. Ukoliko se želi sprečiti i nasleđivanje određene klase, to se takođe može postići stavljanjem rezervisane reči final ispred deklaracije te klase.

Nasledjivanje

Nasleđivanje

Nasleđivanje, kao jedan od osnovnih koncepata objektno-orijentisanog programiranja, postoji i u Javi. Nasleđivanje omogućava pravljenje hijerarhijske klasifikacije. Pomoću nasleđivanja može se napraviti opšta klasa koja definiše zajedničke karakteristike za skup srodnih pojava. Ovu klasu zatim mogu da naslede druge, specifičnije klase, pri čemu svaka dodaje ono što je za nju jedinstveno. Klase se nasleđuju tako što se definicija jedne klase umetne u drugu pomoću rezervisane reči extends. Pogledajmo primer gde klasa B nasleđuje klasu A.

class A {

int i,j;

}

class B extends A {

int k;

}

Može se zaključiti da je opšti oblik nasleđivanja:

Class imepotklase extends imenatklase {

// telo klase

}

Mada potklasa sadrži sve članove svoje natklase, ona ne može da pristupi onim članovima svoje natklase koji su označeni kao privatni (engl. private). Pogledajmo još jedan primer gde klasa BorbeniAvion nasleđuje klasu Avion:

class Avion {

Krilo levo, desno;

void poleti() {…}

void sleti() {…}

}

class BorbeniAvion extends Avion {

Top top;

Bomba bombe[];

void poleti(){…}

void pucaj(){…}

}

Java ne dopušta višestruko nasleđivanje (onako kako je to definisano, recimo, u jeziku C++). Dakle, klasa može da nasledi najviše jednu klasu.

2.7.1. Rezervisana reč super

Ponekad je potrebno da napravite natklasu koja detalje rada čuva za sebe, odnosno sa članovima ka kojima je dozvoljen samo privatan pristup. Kad god potklasa treba da se obrati svojoj neposrednoj natklasi, ona to može da učini pomoću rezervisane reči super. Ova rezervisana reč ima dva opšta oblika. Prvi poziva konstruktor natklase, dok se drugi koristi za pristupanje članu natklase koji je bio skriven članom potklase.

Potklasa može da pozove metodu konstruktora definisanu natklasom, koristeći sledeći opšti oblik:

super (lista parametara);

Lista parametara označava parametre koji su eventualno potrebni konstruktoru natklase. Kada potklasa pozove metodu super(), ona u stvari poziva konstruktor svoje neposredne natklase. Prema tome, metoda super() se uvek odnosi na natklasu neposredno iznad klase koja je poziva.

Drugi oblik upotrebe rezervisane reči super je najprimenljiviji kada imena članova potklase sakrivaju članove sa istim imenom u natklasi. Njen opšti oblik je:

super.član

Pogledajmo sledeći primer hijerarhije klasa:

class A {

int i;

}

// Pravljenje potklase proširenjem klase A.

class B extends A {

int i; // ovo i skriva i u klasi A

B(int a, int b) {

super.i = a; // i u klasi A

i = b; // i u B

}

void show() {

System.out.println(„i u natklasi: “ + super.i);

System.out.println(„i u podklasi: “ + i);

}

}

class UseSuper {

public static void main(String args[]) {

B subOb = new B(1, 2);

subOb.show();

}

}

Program prikazuje sledeći rezultat:

i u natklasi: 1

i u potklasi: 2

Razmotrimo još jedan primer za slučaj da je klasa Osoba apstraktna klasa, a klasa Student njena konkretna klasa.

import java.util.*;

abstract class Osoba{

String MLB;

String ImePrezime;

String Adresa;

Osoba (String MLB1,String ImePrezime1,String Adresa1) {

MLB=MLB1;

ImePrezime=ImePrezime1;

Adresa=Adresa1;

}

void Prikazi(){

System.out.println(„MLB: “ + MLB + “ Ime i prezime: “ + ImePrezime + “ Adresa:“ + Adresa);

}

}

class Student extends Osoba {

String BrojIndeksa;

int Godina;

Student (String MLB1, String ImePrezime1, String Adresa1,

String BrojIndeksa1, int Godina1) {

super (MLB1, ImePrezime1, Adresa1);

BrojIndeksa = BrojIndeksa1;

Godina = Godina1;

}

void Prikazi(){

super.Prikazi();

System.out.println(„Broj indeksa: “ + BrojIndeksa + “

Godina: “ + Godina);

}

}

class Glavna {

public static void main(String args[]) {

/* Osoba o = new Osoba(„1808971715553“,“Mika

Mikic“, „Nusiceva 5“); Ne moze da ima

pojavljivanja.*/

Student k1 = new Student („2502975716662“, „Pera

Peric“, „Beogradska 1“, „F123/02“,3);

k1.Prikazi();

}

}

Rezultat ovog programa je sledeći:

MLB: 2502975716662 ImePrezime: Pera Peric Adresa: Beogradska 1

BrojIndeksa: F123/02 Godina:3

2.7.2. Modifikatori pristupa

U Javi postoje sledeća tri modifikatora pristupa:

1. public: označava da su atribut ili metoda vidljivi za sve klase u programu;

2. protected: atribut ili metoda su vidljivi samo za klase naslednice;

3. private: atribut ili metoda su vidljivi samo unutar svoje klase.

Modifikatori pristupa se navode ispred definicije metode ili atributa. Sledi primer:

class Avion{

protected Krilo levo, desno;

public void poleti() {…}

public void sleti() {…}

}

Na sličan način modifikatori pristupa se mogu primeniti i na celu klasu, na primer:

public class Avion {…}

2.7.3. Zadatak za vežbu nasleđivanja klasa

Programski zahtev 1: pokazati odnos izmedu nadklase i podklase na primeru klasa Osoba (natklasa) i Student (potklasa).

import java.util.*;

class Osoba {

String MLB;

String ImePrezime;

String Adresa;

Osoba(){

MLB =““;

ImePrezime=““;

Adresa=““;

}

Osoba(String MLB1, String ImePrezime1, String Adresa1) {

MLB=MLB1;

ImePrezime=ImePrezime1;

Adresa=Adresa1;

}

void Prikazi(){

System.out.println(„MLB: “ + MLB + “ Ime i prezime: “ +

ImePrezime + “ Adresa:“ + Adresa);

}

}

class Student extends Osoba {

String BrojIndeksa;

int Godina;

Student(){

BrojIndeksa=““;

Godina=0;

}

Student (String MLB1, String ImePrezime1, String Adresa1, String

BrojIndeksa1, int Godina1) {

Super (MLB1, ImePrezime1, Adresa1);

BrojIndeksa = BrojIndeksa1;

Godina = Godina1;

}

void Prikazi(){

super.Prikazi();

System.out.println(„Broj indeksa: “ + BrojIndeksa + “ Godina:

“ + Godina);

}

}

class Glavna {

public static void main(String args[]) {

Student k = new Student();

k.Prikazi();

Student k1 = new Student(„2502975716662“,“Pera

Peric“,“Beogradska 1″,“F123/02″,3);

k1.Prikazi();

}

}

Rezultat:

MLB: ImePrezime: Adresa:

BrojIndeksa: Godina:

MLB: 2502975716662 ImePrezime: Pera Peric Adresa: Beogradska 1

BrojIndeksa: F123/02 Godina:3

Metode

Metode i njihovi parametri

Ako su vam bile nejasne metode, posle ovog posta verujem da će vam laknuti i da ćete shvatiti da Java nije bauk. Preporučujem da pre ovog posta procitate i prethodni o klasama, kako bi vam bilo jasnije. Kasnije ćemo naravno produbljivati znanje i nadovezivati klase, objekte, metode i konstruktore. Ali idemo polako jedno po jedno, i naravno strpljivo.

Kao što je ranije napomenuto, klase sadrže dve komponente: promenljive i metode. Opšti oblik deklarisanja metoda glasi:

Tip ime (lista parametara) {

// telo metode

}

Tip označava tip podatka koje metoda vraća. Ukoliko metoda ne vraća vrednost, njen tip povratnih podataka mora da bude označen sa void. Ime metode je određeno identifikatorom ime. Lista parametara sadrži niz parova razdvojenih zarezima. Parametri su promenljive koje prihvataju vrednosti argumenata prosleđenih metodi u trenutku njenog pozivanja. Metoda vraća vrednost koja se zadaje pomoću naredbe return, koja je oblika: return vrednost.

Može se ukratko reći da metode definišu pristup podacima u većini klasa. Pogledajmo primer sa klasom Kutija, koju ćemo proširiti tako što ćemo dodati metodu u okviru koje će se izračunavati zapremina.

class Kutija {

double sirina;

double visina;

double dubina;

// prikazuje zapreminu kutije

void zapremina() {

System.out.print(„Zapremina je „);

System.out.println(sirina * visina * dubina);

}

}

class KutijaDemo1 {

public static void main(String args[]) {

Kutija mojaKutija1 = new Kutija();

Kutija mojaKutija2 = new Kutija();

/* dodeljuje vrednosti promenljivama instanci objekta mojaKutija1 */

mojaKutija1.sirina = 10;

mojaKutija1.visina = 20;

mojaKutija1.dubina = 15;

/* dodeljuje vrednosti promenljivama

instanci objekta mojaKutija2*/

mojaKutija2.sirina = 3;

mojaKutija2.visina = 6;

mojaKutija2.dubina = 9;

// prikazuje zapreminu prve kutije

mojaKutija1.zapremina();

// prikazuje zapreminu druge kutije

mojaKutija2.zapremina();

}

}

Ovaj program ispisuje sledeće:

Zapremina je 3000.0

Zapremina je 162.0

Kao što se moglo uočiti svaki put kada se pozove metoda zapremina(), prikazuje se zapremina određene kutije.

Ukoliko deo programa ne želi da prikazuje zapreminu na ekranu, već samo da sazna njenu vrednost, onda će metoda zapremina izgledati ovako:

Double zapremina (){

Return sirina*visina*dubina;

}

U okviru klase, poziv na metodu zapremine izgledaće:

Double zapremina;

zapremina=mojaKutija1.zapremina()

system.out.println («Zapremina je + zapremina);

2.6.1. Parametarske metode

Prethodni primer bi mogao da se još više uprosti, i to pomoću metoda koji preuzimaju parametre. Rekli smo da je parametar promenljiva definisana metodom koja pri pozivanju metode prihvata vrednost. Na sledećem primeru:

Int kvadrat (int i) {

Return i*i;

}

parametar predstavlja i, dok je argument vrednost koja se prosleđuje metodi pri njenom pozivanju. Na primer, x=kvadrat(5) prosleđuje vrednost 5 kao argument. Parametar i unutar metode kvadrat() preuzima tu vrednost.

Koristeći parametarske metode, prethodni primer će izgledati:

class Kutija {

double sirina;

double visina;

double dubina;

double zapremina() {

return sirina * visina * dubina;

}

// dodeljivanje dimenzija kutije

void postaviDim(double s, double v, double d) {

sirina = s;

visina = v;

dubina = d;

}

}

class KutijaDemo2 {

public static void main(String args[]) {

Kutija mojaKutija1 = new Kutija();

Kutija mojaKutija2 = new Kutija();

double zapremina;

// inicijalizovanje svake kutije

mojaKutija1.postaviDim(10, 20, 15);

mojaKutija2.postaviDim(3, 6, 9);

// prikazivanje zapremine prve kutije

zapremina = mojaKutija1.zapremina();

System.out.println(„Zapremina je “ + zapremina);

// Prikazivanje zapremine druge kutije

zapremina = mojaKutija2.zapremina();

System.out.println(„Zapremina je “ + zapremina);

}

}

Kao što se vidi, za dodeljivanje dimenzija svake od kutija koristi se metoda postaviDim. Argumenti se kopiraju u parametre metode postaviDim, u okviru koje se vrednosti s, v i d dodeljuju promenljivama sirina, visina i dubina.

Zadatak za vežbu deklarisanja parametarskih metoda

Programski zahtev: napisati parametarsku metodu klase Automat Novca nazvanu Ulaganje i neparametarsku metodu nazvanu Prikazi.

import java.util.*;

class AutomatNovca {

String ImeKlijenta;

double Stanje;

void Ulaganje (double Stanje1) {

Stanje = Stanje1;

}

void Prikazi() {

System.out.println(„Stanje: “ + Stanje);

}

public static void main(String args[]) {

AutomatNovca k = new AutomatNovca();

k.Ulaganje(1300);

k.Prikazi();

}

}

Rezultat programa je:

Stanje: 1300.0

2.6.2. Konstruktori

S obzirom da nije dobro inicijalizovati sve promenljive unutar klase svaki put kada se stvori neka instanca, već je lakše i elegantnije da se sva podešavanja obave u trenutku kada je objekat prvi put napravljen, Java omogućava da objekti sami sebe inicijalizuju pri stvaranju. Ova automatska inicijalizacija se obavlja pomoću konstruktora.

Konstruktor inicijalizuje objekat odmah nakon njegovog stvaranja. On nosi isto ime kao i klasa u kojoj se nalazi, a po sintaksi je sličan metodi. Konstruktor se automatski poziva čim se napravi objekat, pre nego što operator new završi svoj posao. Konstruktori nemaju ni tip povratnih podataka ni tip void, zbog toga što je podrazumevani tip povratnih podataka konstruktora sam tip klase.

Zadatak konstruktora je da inicijalizuje unutrašnje stanje objekta tako da kôd koji pravi instancu odmah naiđe na potpuno inicijalizovan, upotrebljiv objekat. Da bi iskoristili prethodni primer za prikazivanje konstruktora, metodu postaviDim() ćemo zameniti konstruktorom.

class Kutija {

double sirina;

double visina;

double dubina;

// Ovo je konstruktor za kutiju

Kutija() {

System.out.println(„Konstruisem objekat klase Kutija „);

sirina = 10;

visina = 10;

dubina = 10;

}

// izračunava i vraća vrednosti zapremine

double zapremina() {

return sirina * visina * dubina;

}

}

class KutijaDemo3 {

public static void main(String args[]) {

/* deklariše, dodeljuje i inicijalizuje objekte

klase Kutija */

Kutija mojaKutija1 = new Kutija();

Kutija mojaKutija2 = new Kutija();

double zapremina;

// prikazivanje zapremine prve kutije

zapremina = mojaKutija1.zapremina();

System.out.println(„Zapremina je “ + zapremina);

// prikazivanje zapremine druge kutije

zapremina = mojaKutija2.zapremina();

System.out.println(„Zapremina je “ + zapremina);

}

}

Rezultat ovog programa, pri njenom izvršavanju je:

Konstruisem objekat klase Kutija

Konstruisem objekat klase Kutija

Zapremina je 1000.0

Zapremina je 1000.0

Konstruktor Kutija() inicijalizuje objekte mojaKutija1 i mojaKutija2 čim se stvore, i dodeljuje ima iste dimenzije: 10x10x10. Kada se konstruktor izričito ne definiše, Java će za klasu iskoristiti podrazumevani konstruktor koji automatski sve promenljive instanci inicijalizuje vrednošću nula.

U prethodnom primeru smo svim kutijama dodelili iste dimenzije, a ukoliko to ne želimo, onda ćemo koristiti parametarske konstruktore. Na primer, u sledećoj verziji programa Kutija definišemo parametarski konstruktor koji dimenzijama dodeljuje vrednosti zadate preko parametara.

class Kutija {

double sirina;

double visina;

double dubina;

// Ovo je konstruktor klase kutija

Kutija(double s, double v, double d) {

sirina = s;

visina = v;

dubina = d;

}

double zapremina() {

return sirina * visina * dubina;

}

}

class KutijaDemo4 {

public static void main(String args[]) {

Kutija mojaKutija1 = new Kutija (10, 20, 15);

Kutija mojaKutija2 = new Kutija (3, 6, 9);

double zapremina;

zapremina = mojaKutija1.zapremina();

System.out.println(„Zapremina je “ + zapremina);

zapremina = mojaKutija2.zapremina();

System.out.println(„Zapremina je “ + zapremina);

}

}

Rezultat je sledeći:

Zapremina je 3000.0

Zapremina je 162.0

Kao što se vidi, svaki objekat se inicijalizuje vrednostima parametara konstruktora koji se prosleđuju konstruktoru Kutija u trenutku kada operator new pravi objekat.

Zadatak za vežbu deklarisanja konstruktora

Programski zahtev: napisati default i parametarski konstruktor klase AutomatNovca.

import java.util.*;

class AutomatNovca {

String ImeKlijenta;

double Stanje;

AutomatNovca(){

ImeKlijenta = „nepoznato“;

Stanje = 0;

}

AutomatNovca(String ImeKlijenta1, double Stanje1){

ImeKlijenta = ImeKlijenta1;

Stanje = Stanje1;

}

void PrikaziKlijenta(){

System.out.println(„Ime klijenta: “ + ImeKlijenta + “ Stanje:“ + Stanje);

}

public static void main(String args[]) {

AutomatNovca k = new AutomatNovca();

AutomatNovca k1 = new AutomatNovca(„Pera Peric“, 3500);

AutomatNovca k2 = new AutomatNovca();

k.PrikaziKlijenta();

k1.PrikaziKlijenta();

k2.PrikaziKlijenta();

}

}

Rezultat ovog programa pri njenom izvršavanju je:

Ime Klijenta: nepoznatno Stanje = 0.0

Ime Klijenta: Pera Peric Stanje = 3500.0

Ime Klijenta: nepoznatno Stanje = 0.0

2.6.3. Rezervisana reč this

Ponekad je potrebno da metoda ukaže na objekat koji ju je pozvao. Java ovo omogućava pomoću rezervisane reči this, koja se može koristiti unutar bilo koje metode da bi se ukazalo na tekući objekat. Znači, reč this je uvek referenca na objekat za koji je pozvana metoda. Pogledajmo sledeći primer koji koristi rezervisanu reč this:

import java.util.*;

class AutomatNovca {

String ImeKlijenta;

double Stanje;

void Ulaganje (double Stanje1) {

this.Stanje = Stanje1;

}

void Prikazi() {

System.out.println(Stanje);

}

public static void main(String args[]) {

AutomatNovca k = new AutomatNovca();

AutomatNovca k1 = new AutomatNovca();

k.Ulaganje(1300);

k1.Ulaganje(1500);

k.Prikazi();

k1.Prikazi();

}

}

Rezultat ovog programa je:

1300.0

1500.0

Unutar konstruktora Ulaganje, reč this će uvek ukazivati na objekat koji poziva metodu.

2.6.4. Ključna reč final

Ključna reč final se može naći ispred definicije atributa ili metode unutar definicije klase. Ako se nađe ispred atributa, označava atribut kome nije moguće promeniti vrednost. Drugim rečima, final atribut predstavlja konstantu. Inicijalizacija prilikom deklaracije atributa je obavezna. Primer definicije jednog final atributa bio bi:

final int VELICINA = 100;

Ključna reč final ima drugo značenje kod metoda: označava metode koje se ne mogu redefinisati prilikom nasleđivanja date klase. Primer jedne final metode glasi:

final int metoda(int i){…}

2.6.5. Ključna reč static

Ponekad je potrebno definisati član klase koji će se koristiti nezavisno od objekata klase. Članu klase obično se može pristupati samo preko objekta iste klase. Međutim, moguće je napraviti i član koji se samostalno može koristiti, bez referenciranja određene instance.

Kada želite da napravite takav član, njegovu deklaraciju započnite rezervisanom rečju static. Kada član bude statičan, njemu će moći da se pristupi pre nego što bude napravljen ijedan objekat njegove klase i bez referenciranja bilo kog objekta. Takođe, i metode mogu biti statične. Najpoznatiji primer statične metode je main(). Promenljive instanci deklarisane kao statične su, u suštini, globalne promenljive.

Pogledajmo sledeći programski zahtev koji ilustruje kako static atribut Stanje klase KStanje dele dva različita objekta klase KStanje.

class AutomatNovca {

public static void main(String args[]) {

KStanje k = new KStanje();

k.Prikazi();

k.Stanje = 5;

k.Prikazi();

KStanje k1 = new KStanje();

k.Prikazi();

k1.Stanje = 7;

k.Prikazi();

}

}

class KStanje {

static double Stanje;

void Prikazi(){

System.out.println(„Vrednost stanja je: “ + Stanje);

}

static{ Stanje = 2;}

}

Rezultat ovog programa je sledeći:

Vrednost stanja je: 2.0

Vrednost stanja je: 5.0

Vrednost stanja je: 5.0

Vrednost stanja je: 7.0

2.6.6. Metoda finalize

Prethodno smo naveli da se objektima memorija dodeljuje dinamički pomoću operatora new, dok se brisanje nepotrebnih objekata obavlja automatski tehnikom sakupljanje smeća (engl. Garbage collection – GC). Ova tehnika radi tako što kada nema nijedne reference na neki objekat, pretpostavlja da taj objekat više nije potreban i da memorija koju zauzima može da postane raspoloživa.

Različiti Javini izvršni sistemi koristiće različite pristupe sakupljanju smeća. Pored automatske dealokacije memorije, GC je zadužen i za automatsku defragmentaciju memorije. U trenutku dealokacije podrazumeva se da je Java objekat oslobodio ostale resurse koje je koristio (otvorene datoteke, mrežne konekcije, itd.).

Ponekad objekat pre nego što se uništi treba da izvrši neku akciju.Ovo se postiže definisanjem metode finalize, čiji je opšti oblik:

Protected void finalize ()

{

// kôd za finalizaciju

}

Ključna reč protected predstavlja specifikator koji sprečava pristupanje metodi spolja. Metoda finalize će biti pozvana neposredno pre sakupljanja smeća. Ovde je važno naglasiti da metodu finalize ne treba koristiti za oslobađanje zauzetih resursa, jer se metoda finalize ne mora pozvati. Naime, GC sam određuje kada će ukloniti objekat iz memorije i lako se može desiti da se to nikad ne dogodi: program je pokrenut, radio je neko vreme, računar raspolaže sa dovoljno radne memorije, tako da GC nije počeo sa uklanjanjem objekata, i tako sve do završetka rada programa; GC nije uklonio objekat, samim tim nije pozvao metodu finalize i eventualno oslobađanje zauzetih resursa se nije ni desilo.

Klase i objekti

Klase i objekti

Druga vrsta podataka sa kojima operiše Java program su objekti. Objekti predstavljaju osnovni koncept objektno-orijentisane paradigme u modelovanju sistema. Svaki objekat realnog sistema koga posmatramo predstavljamo odgovarajućim objektom koji je sastavni deo modela sistema. Objekte koji imaju zajedničke osobine možemo da opišemo klasom. U tom smislu, objekat je jedna instanca (primerak) svoje klase. Dakle, klasa predstavlja model objekta koji obuhvata atribute i metode. Klasa definiše nov tip podataka. Kada se jednom definiše, ovaj novi tip može da se koristi za pravljenje objekata tog tipa.

Klasa se deklariše pomoću rezervisane reči class. Opšti oblik definicije klase je:

Class imeKlase {

Tip promenljiva1;

Tip promenljiva2;

//…

tip promenljivaN;

tip imeMetode1 (lista parametara) {

// telo metode

}

tip imeMetode2 (lista parametara) {

// telo metode

}

// …

tip imeMetodeN (lista parametara) {

// telo metode

}

}

Podaci ili promenljive su definisane unutar klase, dok je kôd sadržan u metodama. Sledi primer jedne Java klase:

class Automobil {

boolean radi;

void upali() {

radi = true;

}

void ugasi() {

radi = false;

}

}

Klasa ima naziv Automobil, definiše jedan atribut koji se zove radi i logickog je tipa (boolean) i definiše dve metode koje se mogu pozvati nad objektima te klase, metode upali i ugasi.

Kreiranje objekata koji predstavljaju instance (primerke) ove klase može se obaviti na sledeći način:

Automobil mojAuto = new Automobil();

Time je kreiran objekat klase Automobil, koji je nazvan mojAuto. Atributu radi objekta mojAuto može se pristupiti pomoću:

MojAuto.radi

Poziv metodi upali mogao bi da izgleda kao u sledećem primeru:

MojAuto.upali()

Razmotrimo prvi jednostavniji Java program, koji glasi:

class HelloWorld {

public static void main (String args[]) {

System.out.println (“Hello World, “);

System.out.println (“it’s me …”);

}

}

Rezervisana reč class označava definisanje nove klase. Klasa je nazvana HelloWorld. Celokupna definicija klase se nalazi unutar vitičastih zagrada. Svaka klasa može da sadrži više metoda, ali samo jedna je glavna (engl. main). Sa metodom main, počinje izvršavanje svih Java aplikacija.

Rezervisana reč public je specifikator pristupa koja označava da se tom članu može pristupiti i izvan klase u kojoj je član deklarisan. U ovom slučaju metoda main mora biti deklarisana kao public, pošto pri pokretanju programa mora biti povana izvan klase.

Rezervisana reč static dozvoljava da metoda main() bude pozvana bez pravljenja posebne instance klase. To je neophodno jer Javin interpretator poziva metodu main() pre nego što je stvoren ijedan objekat.

Rezervisana reč void samo saopštava prevodiocu da metoda main() ne vraća nikakvu vrednost. Vodite računa da Java razlikuje velika i mala slova, tako Main nije isto što i main.

Metodama možete da prosledite podatke preko promenljivih koje su navedene u zagradi iza imena metode. Ove promenljive se nazivaju parametri. Čak i kada određenoj metodi nisu potrebni parametri, moraćete da napišete praznu zagradu. U metodi main() postoji samo jedan parametar, ali on nije jednostavan. String args[] deklariše parametar args, koji predstavlja niz instanci klase String. Objekti tipa String označavaju znakovne nizove. Znači, kada se program pokrene u niz args biće smešteni eventualni argumenti uneti na komandnu liniju. Treba napomenuti da Java apleti uopšte ne koriste metodu main, jer čitači Weba drugačije pokreću izvršavanje apleta.

Iskazi u okviru metode main() govore šta metoda treba da uradi. U našem slučaju na ekran se ispisuju reči koje su zadate u zagradama. Ispisivanje na ekran se vrši sistemskom metodom system.out.println.

Sledeći korak je da sačuvate i date ime datoteci. U većini programskih jezika možete proizvoljno da izaberete ime datoteke sa izvornim kodom, međutim to nije slučaj u Javi. Datoteka sa izvornim kodom u Javi se zvanično zove kompilatorska jedinica, koja predstavlja tekstualnu datoteku koja sadrži jednu ili više definicija klasa. S obzirom da Java sav kôd smešta unutar klasa, ime određene klase treba da odgovara imenu datoteke koja sadrži program. Znači, Java stavlja sve klase u poseban tekst fajl, koji predstavlja Javin izvršni fajl. Ovaj primer ćete snimiti pod nazivom HelloWorld.java.

Sledeći korak je da kompajliramo naš prvi program. Prevodilac jezika Java zahteva da datoteka sa izvornim kodom ima nastavak .java. Naziv Javinog prevodioca je javac. Ukoliko koristimo MSDos Prompt, na komandnoj liniji otkucaćemo sledeće:

C:\>javac HelloWorld.java

Prevodilac javac će napraviti datoteku HelloWorld.class. Ukoliko je došlo do greške u pisanju koda, javac će odbiti da kompajlira kôd i prijaviće grešku. Datoteka HelloWorld.class će sadržati bajt-kôd programa. Ranije smo objasnili da bajt-kôd predstavlja poluproizvod sa instrukcijama koje treba da izvrši interpretator.

Prevodilac javac ne generiše kôd koji se odmah može izvršavati. Da bismo pokrenuli program, mora se pozvati javin interpretator nazvan java, na sledeći način:

C:\>java HelloWorld

Javina virtuelna mašina izvršava program tako što prvo traži istoimenu klasu, a potom unutar nje metodu main(). Kada se program izvrši, na ekranu će se dobiti sledeća poruka:

Hello World,

It’s me …

Razmotrimo još jedan primer:

class Kutija {

double sirina;

double visina;

double dubina;

}

// Ova klasa deklarise objekat tipa Kutija

class KutijaDemo {

public static void main(String args[]) {

Kutija mojaKutija = new Kutija();

double zapremina;

// dodeljivanje vrednosti promenljivama instanci objekta mojaKutija

mojaKutija.sirina = 10;

mojaKutija.visina = 20;

mojaKutija.dubina = 15;

// izracunava zapreminu kutije

zapremina = mojaKutija.sirina * mojaKutija.visina * mojaKutija.dubina;

System.out.println(„Zapremina je “ + zapremina);

}

}

Datoteku koja sadrži ovaj program treba da nazovete KutijaDemo.java, jer se metoda main() ne nalazi u klasi Kutija, već u klasi KutijaDemo. Prevođenjem ovog programa napravićete dve datoteke .class, jednu za klasu Kutija i drugu za klasu KutijaDemo. Javin prevodilac svaku klasu automatski smešta u datoteku .class. Nije ni neophodno da ove dve klase budu u istoj izvornoj datoteci, možete ih snimiti u posebne datoteke kao Kutija.java i KutijaDemo.java. Da biste program izvršili, morate da pokrenete datoteku KutijaDemo.class, nakon čega će se ispisati sledeći rezultat:

Zapremina je 3000.0

2.5.1. Reference na objekat

Kada se pravi klasa, tada se u stvari pravi novi tip podataka. Novi tip se može upotrebiti za deklarisanje nekog objekta tog tipa. Međutim, pravljenje objekata određene klase izvodi se u dve faze:

1. Prvi korak je deklarisanje promenljive čiji tip odgovara klasi. (ova promenljiva ne definiše objekat, već samo može da ukazuje na njega);

2. Drugi korak je da se toj promenljivoj doda stvarna, fizička kopija objekta. To se izvodi operatorom new koji dinamički (tj. u trenutku izvršavanja) dodeljuje memoriju za objekat i programu vraća referencu na njega. Ta referenca u stvari predstavlja adresu objekta stvorenog operatorom new u memoriji. Referenca se smešta u promenljivu.

Posmatrajući prethodni primer, objekat tipa Kutija je deklarisan ovakvim iskazom:

Kutija mojaKutija = new Kutija();

U ovom iskazu su spojene obe faze pravljenja objekta, inače bi se pisale na duži način, kao što se prikazuje:

Kutija mojaKutija; //deklarisanje reference na objekat

MojaKutija=new Kutija(); //dodeljivanje memorije objektu Kutija

U prvom redu se deklariše promenljiva mojaKutija kao referenca na objekat tipa Kutija.

mojaKutija

Stek

Slika 2.6. Referenca mojaKutija ukazuje na objekat klase Kutija.

Nakon što se ovaj red izvrši, promenljiva mojaKutija sadrži vrednost null, što znači da ona još uvek ne ukazuje na stvarni objekat.

Slika 2.7. Efekat deklarisanja promenljive čiji tip odgovara klasi

U sledećem redu se dodeljuje memorija stvarnom objektu, a promenljivoj mojaKutija se dodeljuje referenca na njega. Pošto se izvrši drugi red, promenljivu mojaKutija možete da koristite kao da predstavlja objekat Kutija. Znači, promenljiva mojaKutija sadrži samo memorijsku adresu objekta Kutija.

Slika 2.8. Dodeljivanje memorije objektu mojaKutija

Kao što se do sada moglo uočiti, opšti oblik upotrebe operatora new koji dinamički dodeljuje memoriju objektu glasi:

promenljiva=new imeklase();

Ovde se promenljiva odnosi na tip klase koja se pravi. Imeklase označava klasu čiji se primerak (instanca) pravi. Imenom klase iza koga slede zagrade određuje se konstruktor klase. Konstruktor definiše šta se događa kada se pravi jedan od objekata klase. Konstruktori su važan deo svih klasa i imaju mnoge značajne atribute.

Sledeći primer prikazuje kreiranje dva objekta klase Automobil i inicijalizaciju referenci, tako da ukazuju na odgovarajuce objekte. Reference se nalaze na steku programa.

Automobil a = new Automobil();

Automobil b = new Automobil();

Situacija koja se nakon ovoga nalazi u memoriji je prikazana na slici 2.9.

Slika 2.9. Dve refence koje ukazuju na dva objekta

Ako se sada izvrši naredba:

b = a;

u memoriji će biti sledeća situacija:

Slika 2.10. Situacija nakon kopiranja referenci

Postavlja se pitanje šta se u ovoj situaciji dešava sa objektom na koga je ukazivala referenca b: taj objekat više nije dostupan ni na jedan način, jer je jedina mogućnost da se nekoj referenci dodeli vrednost ili postojeće reference (tipa b = a) ili reference na novokreiran objekat (tipa a = new …). Kako objekat više nije dostupan, valjalo bi ga ukloniti iz memorije kako bi se izbeglo „curenje memorije”. Java ne poseduje posebnu jezičku konstrukciju kojom se memorija dealocira. Za dealokaciju memorije zadužen je poseban pozadinski proces programa koji se naziva garbage collector („skupljač đubreta”), o čemu će biti reči u narednim poglavljima.

2.5.2. Unutrašnje klase

Od Java verzije 1.1 klasa može, osim atributa i metoda, da poseduje i tzv. unutrašnje klase. Sledi primer:

class Spoljasnja {

void metoda() {…}

class Unutrasnja {

int metoda2() {…}

}

}

U principu, klasa Unutrasnja je vidljiva samo unutar klase Spoljasnja, mada se to može promeniti modifikatorima pristupa na uobičajeni način. Instanca unutrašnje klase se može kreirati i izvan nje, ali samo preko instance spoljašnje klase, kao u sledećem primeru:

Spoljasnja s = new Spoljasnja();

Spoljasnja.Unutrasnja u = s.new Unutrasnja();

Koncept unutrašnjih klasa se najviše koristi prilikom izgradnje grafičkog korisničkog interfejsa, o čemu će kasnije biti reči.

2.5.3. Apstraktne klase

Apstraktne klase su klase koje ne mogu imati svoje instance (objekte). Razlog za to je što je implementacija neke od metoda izostavljena. U primeru:

public abstract class A {

public void metodal(){…}

public abstract void metoda2();

private int i;

}

Metoda metoda2 je proglašena za apstraktnu, korišćenjem ključne reči abstract. Njena implementacija nije navedena. Samim tim, klasa je apstraktna pa se i za nju to mora navesti navođenjem ključne reči abstract ispred class.

2.5.4. Zadatak za vežbu deklarisanja klasa

Napraviti klasu Predmet koja ima atribute SifraPredmeta (int), NazivPredmeta (String) i NazivProfesora(String). Deklarisati objekat klase Predmet i metode UnesiSifruPredmeta, UnesiNazivPredmeta, UnesiNaziv Profesora i PrikaziPredmet. Koristeći navedene metode napuniti objekat. Prikazati objekat na standardnom izlazu.

import java.util.*;

class Predmet{

int SifraPredmeta;

String NazivPredmeta;

String NazivProfesora;

void UnesiSifruPredmeta (int SifraPredmeta1) {

SifraPredmeta = SifraPredmeta1;

}

void UnesiNazivPredmeta(String NazivPredmeta1) {

NazivPredmeta = NazivPredmeta1;

}

void UnesiNazivProfesora(String NazivProfesora1) {

NazivProfesora = NazivProfesora1;

}

void PrikaziPredmet(){

System.out.println(„Sifra predmeta: “ + SifraPredmeta + „\nNaziv predmeta: “ + NazivPredmeta + „\nNaziv profesora: “ + NazivProfesora);

}

public static void main(String args[]) {

Predmet k = new Predmet();

k.UnesiSifruPredmeta(14);

k.UnesiNazivPredmeta(„Internet programiranje“);

k.UnesiNazivProfesora(„prof. Schildt“);

k.PrikaziPredmet();

}

}

Rezultat programa je:

Sifra predmeta: 14
Ime predmeta: Internet programiranje
Naziv profesora: prof. Schildt

Upravljačke naredbe

E, sad počinjemo sa malo ozbiljnijim radom. Verujem da vam je do sada sve islo lako i da ste dobro razumeli ono što sam do sada postavljala, ali sad već ozbiljno počinjemo da se bavimo javom.

Upravljačke naredbe se koriste za kontrolisanje toka programa i njegovog grananja na osnovu promena stanja programa. Javine upravljačke naredbe se mogu svrstati u sledeće kategorije:

1. naredbe uslovljavanja,

2. naredbe ciklusa,

3. naredbe skoka.

1. Java podržava dve naredbe uslovljavanja, i to if i switch. Naredbom if se program može usmeriti duž jednog od dva različita puta. Opšti oblik naredbe if:

If (uslov) naredba 1;

Else naredba 2;

Primer:

Int a, b;

If (a<b) a=0;

Else b=0;

Ugnježdeno uslovljavanje je pojava da se jedna if naredba nalazi unutar druge naredbe if ili else. Evo jednog primera:

If(i=10) {

If(j<20) a=b;

If(k>100) c=d;

else a=c;

}

else a=d;

Da bi se izbegla lestvica if-else-if, koristi se naredba switch. Njen opšti oblik je:

Switch (izraz) {

Case vrednost1:

// niz naredaba

break;

case vrednost2:

// niz naredaba

break;

.

.

.

case vrednostN:

//niz naredaba

break;

default:

// niz podrazumevanih naredaba

}

Evo jednostavnog primera u kome se koristi naredba switch:

String GodisnjeDoba;

Switch (mesec) {

Case 12:

Case 1:

Case 2:

GodisnjeDoba = „zima”;

Break;

Case 3:

Case 4:

Case 5:

GodisnjeDoba=„prolece”;

Break;

Case 6:

Case 7:

Case 8:

GodisnjeDoba=„leto”;

Break;

Case 9:

Case 10:

Case 11:

GodisnjeDoba=„jesen”;

Break;

Default:

GodisnjeDoba=„nepostojeci mesec”;

}

Možda ste primetili da u prethodnom objašnjavanju tipova podataka i nizova nismo pomenuli znakovne nizove ili tip znakovnog niza String. Nije u pitanju to što Java ne podržava takav tip podataka, već to da je Javin tip za podatke znakovnog niza String nije prost tip, već se definiše kao objekat. Tip String se koristi za deklarisanje promenljive znakovnog niza. Promenljivoj tipa String se može dodeliti tekst u navodnicima.

2. Javne naredbe ciklusa obuhvataju: for, while i do-while. Ovim naredbama se prave petlje koje izvršavaju isti skup instrukcija onoliko puta koliko je potrebno da se ispuni zadati uslov. Petlja while je Javina osnovna petlja. Ona ponovljeno izvršava naredbu ili blok sve dok je upravljački izraz tačan. Njen opšti oblik je:

While (uslov) {

// telo petlje

}

Na primer:

int brojac=0;

while(brojac<10) {

f=x-brojac;

Brojac ++;

}

Petlja do-while uvek izvršava telo petlje barem jednom, jer se uslovni izraz nalazi na njenom kraju. Njen opšti oblik je:

Do {

// telo petlje

} while (uslov);

Na primer:

int k=0;

do {

System.out.println(”k= ”+k);

k++;

} while (k<=10);

Opšti oblik naredbe for glasi:

For (inicijalizacija; uslov; iteracija) {

// telo

}

Petlja for radi na sledeći način: kada petlja započne rad, izvršava se inicijalizacija koja dejstvuje kao brojač ciklusa petlje. Zatim se ispituje uslov koji poredi upravljačku promenljivu petlje sa zadatom ciljnom vrednošću. Ako je izraz tačan, izvršava se telo petlje. Ako je netačan, petlja se završava. Zatim se izvršava iteracija. Na primer:

for (int n=10;n>0;n–)

Kada promenljivu deklarišete unutar petlje for, tada njena važnost prestaje sa završetkom petlje for. Evo još jednog primera:

for (int a=1, b=4;a<b;a++, b–)

Takođe, možete praviti i ugnježdene petlje for:

for (int i=0;i<10;i++){

for (int j=i; j<10; j++)

}

3. Java podržava tri naredbe za skokove: break, continue i return. Ove naredbe omogućavaju da se izvršavanje programa ne nastavi sa sledećom po redu, već s nekom drugom naredbom. Naredba break u Javi ima tri namene. Prva, za završavanje niza naredbi u naredbi switch. Drugo, može poslužiti za izlazak iz petlje i treće, kao „civilizovan” oblik naredbe goto. Njen opšti oblik je: break oznaka. Oznakom se označava blok naredbi. Kada se izvrši ovaj oblik naredbe break, izvršavanje programa se nastavlja posle označenog bloka. Retke su situacije u kojima je opravdana primena naredbe continue, jer Java obezbeđuje bogat skup naredbi za petlje koje mogu da reše većinu potreba. Poslednja naredba je return, koja se koristi za bezuslovan izlazak iz metode.

Ovde treba napomenuti da Java podržava dva stila komentara:

1. višeredni komentar koji počinje oznakama /*, a završava se oznakama */;

2. jednoredni komentar započinje oznakama // i završava se na kraju tekućeg reda.

Operatori

Operatori koji služe za gradnju Java izraza su operatori koji su praktično preuzeti iz jezika C++. Možemo ih grupisati u nekoliko grupa:

1. aritmetički operatori (+, -, *, /, %, ++, +=, -=, –, itd.),

2. relacioni operatori (==, , =, !=, >=, <=),

3. logički operatori (&&, | |, !),

4. bit-operatori (&, |, !),

5. operator dodele (=).

1. Što se tiče aritmetičkih operatora, Java uvodi specijalne operatore koji kombinuju aritmetičku operaciju sa operacijom dodeljivanja. U programiranju se često srećete sa naredbom primera a=a+5; dok u Javi ovu naredbu možete da napišete kao: a+=5. Evo još nekoliko primera:

x=x+1, dok u Javi x++;

x=x-1, u Javi x–;

x=x+1; y=x, dok u Javi y=++x;

2. Relacioni operatori ili operatori poređenja utvrđuju odnos jednog operanda prema drugom. U tabeli 2.2 se daje njihov detaljniji opis.

Tabela 2.2. Relacioni operatori

Operator

Rezultat

==

Jednako

!=

Različito

>

Veće od

<

Manje od

>=

Veće od ili jednako

<=

Manje od ili jednako

3. Logički operatori rade samo sa operandima tipa boolean. U tabeli 2.3 se prikazuju svi logički operatori sa njihovim rezultatima.

Tabela 2.3. Logički operatori

Operator

Rezultat

&

Logička konjunkcija (AND- i)

|

Logička disjunkcija (OR-ili)

^

Logička isključiva disjunkcija (isključivo OR ili XOR – isključivo ili)

||

Kratkospojena disjunkcija

&&

Kratkospojena konjunkcija

!

Logička unarna negacija (NOT – ne)

&=

Dodeljivanje uz logičku konjunkciju

|=

Dodeljivanje uz logičku disjunkciju

^=

Dodeljivanje uz logičku isključivu disjunkciju

==

Jednako

!=

Različito

?:

Trojni operator uslovne dodele

Osnovni logički operatori rade sa vrednostima tipa boolean na isti način kao sa bitovima celih brojeva (tabela 2.4). Logički operator ! invertuje vrednost: !true==false i !false==true.

Tabela 2.4. Rezultati operacija logičkih operatora sa vrednostima tipa boolean.

A

B

A|B

A&B

A^B

!A

False

False

False

False

False

True

True

False

True

False

True

False

False

True

True

False

True

True

True

True

True

True

False

False

Java ima dva zanimljiva logička operatora koji se ne sreću u većini drugih računarskih jezika. To su izmenjene verzije logičkih operatora konjunkcije i disjunkcije koje su poznate pod imenom kratkospojenih logičkih operatora.

Kao što je poznato, operator disjunkcije daje rezultat true kada A ima vrednost true, bez obzira na vrednost promenljive B ili daje rezultat false kada A ima vrednost false, bez obzira na vrednost promenljive B.

Ako umesto operatora | i & upotrebimo operatore || i &&, Java se neće truditi da izračunava desni operand kada se rezultat izraza može dobiti samo iz levog. Pogledajmo primer:

if (delilac!=0 && broj/delilac>10)

S obzirom da je upotrebljen kratkospojeni oblik konjunkcije &&, nema opasnosti od pojave problematične situacije (delilac ==0) u vreme izvršavanja. Da je ovaj red sadržao običnu verziju konjunkcije &, izračunavale bi se obe strane izraza, što bi u slučaju da je delilac jednak 0 izazivalo grešku tokom izvršavanja.

Java ima i specijalni trojni operator koji može da zameni određene vrste uslovnih iskaza. Njen opšti oblik je:

izraz1? izraz2:izraz3

Ako izraz1 ima vrednost true, onda se izračunava izraz2, u suprotnom izračunava se izraz3. Rezultat operacije ? je rezultat onog izraza koji se izračunava. Izraz2 i izraz3 obavezno moraju da vraćaju vrednost istog tipa koja ne sme da bude tipa void. Evo primera primene:

odnos=delilac==0?0:broj/delilac;

Ukoliko je delilac jednak 0, tada se izračunava izraz između znaka pitanja i dvotačke i njegov rezultat se koristi kao rezultat čitave operacije ? Ako delilac nije nula, izračunava se izraz iza dvotačke i rezultat smešta u promenljivoj odnos.

4. Java definiše nekoliko operatora sa bitovima koji se mogu primeniti na celobrojne tipove, kao što su long, int, short, char i byte. Operatori nad bitovima i njihov rezultat se prikazuju u tabeli 2.5.

Tabela 2.5. Rezultati operatora nad bitovima

Operator

Rezultat

~

Negacija nad bitovima jednog operanda (NOT)

&

Konjukcija nad bitovima (AND)

|

Disjunkcija nad bitovima (OR)

^

Isključiva disjunkcija nad bitovima (XOR)

>>

Pomeranje udesno

>>>

Pomeranje udesno sa unošenjem nula

<<

Pomeranje ulevo

&=

Dodeljivanje uz konjunkciju nad bitovima

|=

Dodeljivanje uz disjunkciju nad bitovima

^=

Dodeljivanje uz isključivu disjunkciju nad bitovima

>>=

Dodeljivanje uz pomeranje udesno

>>>=

Dodeljivanje uz pomeranje udesno sa unošenjem nula

<<=

Dodeljivanje uz pomeranje ulevo

Logički operatori koji rade nad bitovima i rezultati svake operacije su prikazani u tabeli 2.6.

Tabela 2.6. Rezultati operacije logičkih operatora nad bitovima

A

B

A|B

A&B

A^B

~A

0

0

0

0

0

1

1

0

1

0

1

0

0

1

1

0

1

1

1

1

1

1

0

0

Operator za pomeranje u levu stranu << sve bitove broja pomera ulevo zadati broj puta. Opšti oblik njegove primene je:

vrednost<<broj puta

Ovde broj puta označava broj pomaka ulevo svih bitova vrednosti datog broja. To znači da operator << pomera ulevo sve bitove za broj mesta zadat parametrom broj puta. Pri svakom pomaku ulevo, najznačajniji bit izlazi iz opsega i gubi se, a na desni kraj dolazi nula.

5. Operator dodeljivanja je znak jednakosti, čiji je opšti oblik:

promenljiva=izraz;

Evo primera ulančanog dodeljivanja:

int x, y, z;

x=y=z=100;