Detta avsnitt berättar mer om klasser i Java och beskriver koncept som klassvariabler, klassmetoder, inkapsling, synlighet, paket, slutgiltiga klasser och metoder. Det här är sånt som du bör vara bekant med. Detaljerna är inte superviktiga, men om du stöter på begreppen i text eller i kod bör du känna igen dem.
Några frågeställningar:
Exempel: Matematiska konstanter
Exempel: Matematiska bibliotek
Exempel (igen): Matematiska konstanter
Exempel:
static int x;
En klassvariabel
Den statiska variabeln counter
håller reda på hur många objekt som
skapats i klassen X
.
class X { static int counter = 0; int number; X () { counter = counter + 1; number = counter; } }
X a = new X(); X b = new X(); X c = new X(); System.out.println(c.number);
Variabeln c
får ordningsnummer 3.
Den statiska variabeln X.counter
lagrar antal objekt i klassen.
Ett exempel ur Skansholms bok (kapitel 3):
Anta att vi har en klass Konto
med
räntesats
saldo
Här har alla konton samma räntesats, men varje konto har sitt eget saldo. (Hur skulle det annars se ut?)
Ett exempel med en klassmetod.
Vad beräknar denna metod?
class F { static double m(double x, double y) { return (x + y) / 2; } }
Anropet F.m(4.2, 9)
ger resultatet 6.6
.
Notera: klassmetoder och klassvariabler gör det lätt att skriva
program som inte följer principerna för objektorienterad
programmering. Om man vill lära sig OOP är det lämpligt att till en
början undvika static
.
public class V { private int x; public void setX(int x1) { x = x1; } public int getX() { return x; } }
Vi kan inte komma åt instansvariabeln x
direkt:
V v; v.x = ...
är inte tillåtet.
Men med metoderna setX()
och getX()
kan värdet på x
läsas och skrivas.
En instansvariabel, klassvariabel eller metod kan deklareras
private
. Då kan variabeln eller metoden bara användas i klassen.
Alternativet, public
är default (nästan).
private
.Motiv: Paketbegreppet ger en slags modularisering av större program. Det är ofta lämpligt att samla relaterade klasser i ett paket. Paket gör det möjligt att undvika namnkonflikt om man av nån anledning definierar olika klasser med samma namn. Klasser i ett paket kan dela definitioner som ej är synliga utåt.
(Paket kommer inte att spela någon större roll i denna kurs, men ni bör vara bekanta med begreppet. Ni kommer att komma i kontakt med paket när ni använder olika bibliotek.)
java.io
,
java.lang
, java.applet
och java.swing
.String
, och ett fullständigt namn, till exempel
java.lang.String
.Man talar om att en viss klass ska ingå i ett visst paket med en deklaration
package mittPaket;
som ska stå först i filen.
Precis som en klass i Java (normalt) definieras i en fil med samma
namn, måste alla .class
-filer som ingår i ett visst paket finnas i en
mapp (directory) med samma namn.
Ett paket kan innehålla andra paket. Exempel:
mittPaket.ettAnnatPaket
Klassfilerna till paketet ettAnnatPaket
ska ligga i mappen
ettAnnatPaket
som i sin tur ska finnas i mappen mittPaket
.
För att komma åt en klass i ett visst paket kan man använda klassens fullständiga namn, tex
mittPaket.KlassNamn
eller
mittPaket.ettAnnatPaket.KlassNamn
(Java tillåter att det finns en klass med namnet KlassNamn
i båda
paketen.)
Man kan importera en viss klass eller ett visst paket, tex
import mittPaket.KlassNamn
eller
import mittPaket.ettAnnatPaket.KlassNamn
För att importera alla klasser i ett visst paket skriver man:
import mittPaket.*;
eller
import mittPaket.ettAnnatPaket.*;
Om man importerar två klasser med samma korta namn (och använder detta namn) ger kompilatorn ett felmeddelande.
Exempel:
import java.util.*; import javax.swing.*; class Foo { Timer t; }
Både java.util
och javax.swing
(två paket) definierar en klass Timer.
Konflikten kan lösas genom att man explicit anger vilken klass man vill använda. Lägg till följande deklaration:
import javax.swing.Timer;
så kompilerar programmet.
Hur hittar kompilatorn källkodsfilerna vid kompilering?
Vid kompilering från kommandoraden gäller:
foo.Bar
letar kompilatorn
efter en mapp foo
och hoppas hitta en fil Bar.class
i den.foo
efter en fil
Bar.java
. Om en sådan fil finns kompileras den och .class
-filen hamnar
i samma mapp.Integrerade utvecklingsmiljöer (IDE) brukar lägga källkodsfiler och objektkodsfiler på olika platser i filsystemet.
En systemvariabel CLASSPATH
kan användas för att styra var program som
kompilatorn (javac)
och run-time systemet (java)
placerar och söker
efter .java
- och .class
-filer.
(Vanligtvis behöver du inte tänka så mycket på de här sakerna, men om du skulle stöta på problem rekommenderar jag relevant dokumentation, till exempel http://docs.oracle.com/javase/tutorial/java/package/managingfiles.html)
Om man inte anger synlighet för ett namn kommer namnet att vara synligt för andra klasser inom samma paket.
Reglerna för synlighet sammanfattas i denna tabell:
— | public | "paket" | protected | private |
---|---|---|---|---|
Klassen | ja | ja | ja | ja |
Annan klass (samma paket) | ja | ja | ja | nej |
Subklass (annat paket) | ja | nej | ja | nej |
Annan klass (i annat paket) | ja | nej | nej | nej |
Sammanfattning:
private
—endast synligt i klassenpublic
—tillgänglig för allaprotected
—som "paket", men även tillgänglig för subklasser.Notera att protected
lite paradoxalt ger mindre skydd än om man inte
anger någon synlighet. protected
används sällan.
Konstanter deklareras med nyckelordet final
.
class Person { int ålder; final String namn; Person (String n, int å) { ålder = å; namn = n; } }
En instansvariabel som deklarerats med final
får ett värde när objektet
skapas. Detta värde kan inte modifieras efteråt.
Även klassvariabler kan deklareras static. Här är tex definitionen av
pi i java.lang.Math
:
public static final double PI = 3.14159265358979323846;
Vi kan deklarera klasser och metoder med nyckelordet final
.
Motivering: Ger effektivare kod. Gör det möjligt för en konstruktör av en klass att styra hur andra bygger vidare på klassen.