Klassenvariable initialisieren

Status
Nicht offen für weitere Antworten.

Reinski

Mitglied
Tach zusammen!

Ich bin noch neu bei Java und hab deshalb ein paar grundlegende Fragen zur Verwendung von statischen Variablen und Methoden.

In einer Library habe ich eine Klasse die Klassenmethoden besitzt (also als static deklariert). Diese Methoden stellen allgemeine Datenbank-Operationen zur Verfügung auf die ich hier nicht weiter eingehen muss.
Die DB-Verbindung wird in einem ebenfalls statischen Connection-Object gespeichert.

Hier etwas Beispielcode mit einem Konstruktor und der statischen Methode getPlayerListItems, die dazu dient, ein Array direkt von der Datenbank zu füllen.
Code:
public class clsPlayerDB {
    private static Connection conn;
    
    /** Opens the specified player from the database. */
    public clsPlayerDB(long playerId) throws SQLException { 
        ResultSet result;
        try {
            // SQL statement (uses static Connection object)
            java.sql.Statement stmt = conn.createStatement();
            result = stmt.executeQuery("SELECT * FROM Player WHERE PlayerID=" + playerId);
            result.next();
        } catch (SQLException ex) {
            ex.printStackTrace();
            throw ex;
        }
        fillFromResultSet(result);
        result.close();        
    }       

    public static clsListItem[] getPlayerListItems(long clubId) throws SQLException {
        ResultSet result;
        clsListItem itm[];
        int i = 0;

        try {
            // prepare SQL statements
            java.sql.Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
            // read all clubs
            result = stmt.executeQuery("SELECT * FROM Player WHERE ClubID = " + clubId);
            result.last();
            i = result.getRow();
            if ( i > 0 ) {
                itm = new clsListItem[i];
                i = 0;
                result.beforeFirst();
                while (result.next()) {
                    itm[i++] = new clsListItem(result.getString("FirstName") + " " + result.getString("LastName"), result.getLong("PlayerID"));
                }
                return itm;
            } else {
                return null;
            }
        } catch (SQLException ex) {
            ex.fillInStackTrace();
            throw ex;
        }
    }
Der Code an sich funktioniert, nur kann es sein, dass aus der Anwendung die statische Methode aufgerufen wird, bevor conn initialisiert wurde.
Wie gesagt, handelt es sich um eine Library, die ja auch von anderen benutzt werden kann. Deshalb bin ich auf der Suche nach dem passenden Ort um dieses Connection-Objekt zu initialisieren und dabei die OO-Prinzipien (insb. Kapselung) einhalten möchte. Wo mache ich das am besten? Für Aufrufe von Klassenmethoden gibt es ja keine 'Konstruktoren' die vor der ersten Verwendung aufgerufen werden, oder?
Muss ich also eine öffentliche statische Init-Methode schreiben?
Das fände ich eher unsauber, da dann der Entwickler der mit der Bibliothek und dieser Klasse arbeitet selbst dafür sorgen muss, dass er diese Init-Methode vor der ersten Verwendung aufruft. :noe:
Natürlich könnte ich auch in allen statischen Methoden das conn-Objekt auf null prüfen, was bei vielen Methoden aber auch nicht sehr elegant ist. ???:L
Ich muss noch dazu sagen, dass die Herstellung der DB-Verbindung hardkodiert ist, also keine Informationen von 'außen' dafür nötig sind. Wie wird sowas am saubersten in Java realisiert?
Wäre toll, wenn mir jemand weiter helfen könnte.
Gruß!

reinski
 

merxleben

Aktives Mitglied
Hallo,

ich persönlich habe gute Erfahrungen damit gemacht, dass ich eine Klasse entwickelt habe, die nur für die Kommunikation mit der Datenbank zuständig ist. Diese Klasse erzeugt dann auf Anfrage die benötigten Objekte, wie in deinem Fall den Player. Wenn du dann noch mit einer abstrakten Basisklasse für die Datenbankkommunkation arbeitest, dann kannst du ohne weiteres die unterschiedlichsten Datenbanken oder auch Dateien zur Speicherung benutzen.

Mal kurz zur Demonstration


Code:
public class DBConnection {

    Connection conn;

    public DBConnection() {
    }

    public abstract Player getPlayer(int Id);
    
}

public class MySQLDB extends DBConnection {

    public MYSQLDB() {
    //initialisiere conn
    }

    public Player getPlayer(int Id) {
    ...
    }
}

public class Player {
    .
    .
    .
}

somit hast du ganz klar die Ebenen Datenhaltung und Anwendungslogik getrennt. Und außerdem bist du nicht mehr auf statische Methoden angewiesen, die ich persönlich versuche zu vermeiden.

Mal als kleiner Vorschlag von mir

Martin
 

Reinski

Mitglied
Hi Martin,

vielen Dank für den Vorschlag. Die Sache mit abstrakten Klassen ist noch neu für mich, das werd ich morgen mal ausloten.
Gruß!

reinski
 

Reinski

Mitglied
merxleben hat gesagt.:
Und außerdem bist du nicht mehr auf statische Methoden angewiesen, die ich persönlich versuche zu vermeiden.
Eigentlich finde ich das Konzept der statischen Klassen/Methoden/etc ganz gut. Wieso vermeidest du die Verwendung?
Gibt es dafür Gründe?
Gruß!

reinski
 

L-ectron-X

Gesperrter Benutzer
Es widerspricht dem OO-Gedanken.
Alles, was statisch ist, kann in deinem Programm nur einmal existieren. Die Änderung eines statischen Wertes in einer Klasse bewirkt die Änderung in allen Klassen, die mit diesem Wert arbeiten.
 

Murray

Top Contributor
Zur ursprünglichen Frage, falls Du beim statischen Ansatz bleiben willst:

Zur Initialisierung kannst Du z.B. einen "static initializer" schreiben; der würde so aussehen

Code:
public class clsPlayerDB {
   
    private static Connection conn;

    /* Dieser "static initializer" wird durchlaufen, bevor die erste Instanz dieser Klasse erzeugt
        wird und bevor eine statische Funktion aufgerufen oder auf ein statisches Member
        zugegegriffen wird */
    static {
      conn = ...;
    }
   
    /** Opens the specified player from the database. */
    public clsPlayerDB(long playerId) throws SQLException { 
  

   /* ... */
}

Mir persönlich gefällt das Konzept der "lazy initialization" besser, dazu musst Du den Zugriff auf conn konsequent durch eine Methode getConnection() kapseln. Um zu verdeutlichen, dass die Variable conn auch innerhalb der deklarierenden Klasse "tabu" ist, würden ich sie in _conn umbenennen; ich bin aber nicht sicher, inwieweit das den Coding-Conventions entspricht.

Die Methode getConnection implementierst Du dann so:
Code:
public static getConnection() {
  if (_conn == null) {
    _conn = ...;
  }
  return _conn;
}

Mit diesem Ansatz hat man den Vorteil, dass die Ressource (hier die Connection) erst dann angelegt wird, wenn man sie zum ersten Mal braucht.

OT: Klassenname schreibt man normalerweise groß

//EDIT: Typo
 

personenkult

Aktives Mitglied
Hallo,

das umbenennen ist egal.. totzdem würde ich das nach dem "singleton pattern" implementieren.

Code:
static private Connection connection;
static public getInstance() {
  if(connection==null) {
    connection = new ..;
  }
  return connection;
}


Der Vorteil ist halt, dass du bei dieser Methode wirklich erst dann instanziierst, wenn du es wirklich benötigst. Und dann auch immer nur ein Objekt vorhanden ist. Quasi das, was "Murray" schon zum Schluss meinte ;)
 

RaoulDuke

Bekanntes Mitglied
Bei diesem Singleton mit "lazy initialization" sollte man aber daran denken getInstance synchronized zu machen.
 

merxleben

Aktives Mitglied
Hallo,

Reinski hat gesagt.:
Eigentlich finde ich das Konzept der statischen Klassen/Methoden/etc ganz gut. Wieso vermeidest du die Verwendung?
Gibt es dafür Gründe?
Gruß!

reinski

Nachdem du schon einige Hinweise zur Implementierung bekommen hast, will ich nochmal kurz daruaf eingehen warum ich statische Methoden versuche zu vermeiden. Gleich vorneweg es gibt auch gute Gründe zum Einsatz von statischen Methoden, dazu aber später.

Wie schon erwähnt widerspricht das dem OOP Gedanken, aber das könnte einem ja egal sein. Allerdings gibt es noch handfeste technische Gründe die gegen den exzessiven Einsatz von statischen Methoden sprechen.

Ein Grund hierfür liegt darin, dass statische Methoden nur auf statische Variablen zugreifen können. Diese statischen Variablen oder Attribute kann man auch als Klassenattribute bezeichnen, und wie der Name schon sagt haben diese Attribute in allen Instanzen einer Klasse immer denselben Wert. Damit kannst du also keine zwei Instanzen einer Klasse erzeugen, die sich im Wert eines Klassenattributs unterscheiden. Sobald du also mehr als eine Instanz einer Klasse benötigst kommst du mit statischen Attributen und Methoden nicht mehr aus, da diese(die Instanzen) sonst nicht mehr anhand der Werte ihrer Attribute unterscheidbar sind.

Warum gibt es dann überhaupt statische Attrbute und Methoden. Als ein Einsatzbereich wie schon erwähnt das Singleton Pattern. Hierbei wird sichergestellt, das überall inerhalb einer Anwendung nur genau eine Instanz einer Klasse verwendet wird, wie zum Beispiel in deinem Fall die Datenbankverbindung.

Doch nochmal kurz was zur Implementierung. Ich vermute mal, dass du nicht nur eine Klasse von Objekten in deiner Datenbank speichern möchtest. Daher würde ich empfehlen, dass du das Connection Objekt aus deiner Playerklasse rausnimmst und wirklich eine Klasse für den Datenbankzugriff verwendest.

Mal kurz umrissen sähe das folgendermassen aus

Code:
public class DBConnection {

    private static DBConnection;

    private DBConnection() {
    }

    public static getConnection() {
        if(conn==null) {
            conn = new DBConnection();
        }
        return conn;
    }

    // jede Menge Zugriffsmethoden auf die Datenbank

    public Player getPlayer(int id) {
    .
    .
    }

    ...

}

Verwendet wird das dann folgendermaßen

Code:
DBConnection conn = DBConnection.getConnection();
Player = conn.getPlayer(id);

Das soll erstmal reichen. Ich hoffe, ich konnte deutlich machen, warum man statische Methoden nur sehr sparsam einsetzen sollte.

Vielleicht könntest du mal darlegen, worin du den Vorteil von statischen Methoden siehst.

Martin
 

Reinski

Mitglied
personenkult hat gesagt.:
Quasi das, was "Murray" schon zum Schluss meinte ;)
Bis auf den Methodennamen getInstance statt getConnection sind Eure Beispiele ja auch identisch. ;)

Aber danke für die Hinweise, der statische Initialisierer war genau, was ich ursprünglich gesucht habe.
Wusste nicht, dass das so geht... :)

Abgesehen davon haben mich die kritischen Hinweise zur Verwendung von statischen Methoden darauf gebracht, dass meine Methode
Code:
public static clsListItem[] getPlayerListItems(long clubId) throws SQLException {
    ....
}
tatsächlich nicht dem OO-Gedanken entspricht.
Natürlich gibt es neben der Player-Klasse auch andere, darunter eine Club-Klasse. D.h. ich habe jetzt die Methode als Instanzmethode der Club-Klasse implementiert:
Code:
public class clsClubDB {
    private long id;
    ...
    public clsListItem[] getPlayerListItems() throws SQLException {
        //liefert liste der Spieler dieses Clubs
        ...
    }
Irgendwie hatte ich quasi den Wald vor lauter Bäumen nicht gesehen... ;)

merxleben hat gesagt.:
Doch nochmal kurz was zur Implementierung. Ich vermute mal, dass du nicht nur eine Klasse von Objekten in deiner Datenbank speichern möchtest. Daher würde ich empfehlen, dass du das Connection Objekt aus deiner Playerklasse rausnimmst und wirklich eine Klasse für den Datenbankzugriff verwendest.
Ich gehe in meiner Anwendung sogar einen Schritt weiter: Es gibt zu jeder Entität (Spieler, Club, etc) jeweils eine Klasse für die Funktionalität und eine für den Datenbankzugriff. Denn alle DB-Zugriffe in einer einzigen Klasse zu halten, wird mir zu unübersichtlich.

Die Methoden, die eine Liste von Objekten zurückliefern, gab es nicht nur für Player, sondern auch für die meisten anderen Klassen. Die Verlagerung jeweils in die nächsthöhere Klasse (wie beschrieben zB. von Player-Klassen-Methode in eine Club-Instanz-Methode) brachte mich dahin, ganz oben ein Welt-Objekt (clsWorldDB) einzuführen, in dem dann alle Methoden untergebracht werden, die sich nicht auf Instanzen der anderen Klassen beziehen.
Mit diesem Ansatz kann ich dann sogar ganz auf statische Variablen verzichten (auch die statische Connection), da sich alle Client-Objekte auf die connection ihrer clsWorldDB-Instanz beziehen können.
So hantiert die eigentliche Anwendung letztendlich mit einer Instanz einer clsWorld-Klasse (statt einer statischen Klasse), was es dann auch zulassen würde, mehrere "Welten" von unterschiedlichen Datenbanken gleichzeitig zu handhaben.
Mit meinem alten Ansatz wäre das so ja nicht möglich gewesen.

Ob das tatsächlich praktikabel ist, wird sich erweisen.
Auf jeden Fall hab ich jetzt gerafft, dass mein Festhalten an statischen Elementen in erster Linie aus mangelnder Verfolgung des OO-Konzepts herrührte. :oops: Danke dafür! :toll:
Gibt es eigentlich einen Satz Prüf-Richtlinien für Objektorientiertheit - analog zu den Normalformen bei ER-Datenmodellen? :lol:
Gruß!

reinski
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
S Variablen Klassenvariable über Objekt aufrufen Java Basics - Anfänger-Themen 16
U Methode übernimmt nicht veränderte klassenvariable Java Basics - Anfänger-Themen 5
G Unterschied Instanz- Klassenvariable Java Basics - Anfänger-Themen 11
Orkanson Klassenvariable oder Instanzvariable Java Basics - Anfänger-Themen 9
J Problem bei Zugriff auf Klassenvariable Java Basics - Anfänger-Themen 3
W Mit MEthode auf Klassenvariable zugreifen Java Basics - Anfänger-Themen 22
M Variablennamen als Parameter gleich Var. als Klassenvariable Java Basics - Anfänger-Themen 2
P unterschied Instanzvariable und Klassenvariable Java Basics - Anfänger-Themen 3
B Klassenvariable zuweisen in Konstrktor Java Basics - Anfänger-Themen 2
T Standardkonstruktor, Attribute initialisieren Java Basics - Anfänger-Themen 5
Lion.King Array deklarieren und initialisieren Java Basics - Anfänger-Themen 5
M Variable in einer Schleife initialisieren Java Basics - Anfänger-Themen 46
M Wie lassen sich Objektkonstanten initialisieren, wenn sie eine Bedingung erreichen? Java Basics - Anfänger-Themen 6
R Ein Multidimensionales String Array initialisieren und Deklarieren Java Basics - Anfänger-Themen 2
F Initialisieren eines Web-Mp3 Players in Tabs durch "booleans" erst wenn Tab geöffnet wird ...? Java Basics - Anfänger-Themen 1
C initialisieren eines arrays richtiger Größe und mit geeignetem Datentyp Java Basics - Anfänger-Themen 26
U Problem mit dem initialisieren meines Strings in einer Schleife Java Basics - Anfänger-Themen 5
M Arrays mit mehreren Werten über JOptionPane initialisieren Java Basics - Anfänger-Themen 12
J Ist es möglich einen int Array wirklich leer zu initialisieren oder zu füllen? Java Basics - Anfänger-Themen 21
C Arrays - deklarieren, initialisieren? Ist das ein Objekt? Java Basics - Anfänger-Themen 3
I Wo am besten eine String Konstante initialisieren? Java Basics - Anfänger-Themen 5
X Attribut initialisieren Java Basics - Anfänger-Themen 1
M Deklarieren und Initialisieren von Arrays Java Basics - Anfänger-Themen 3
Dawinartor Erste Schritte Statisch, Initialisieren, Deklarieren, ... Java Basics - Anfänger-Themen 1
L Variable in If-Statement initialisieren Java Basics - Anfänger-Themen 4
C Verschachteltes Array initialisieren Java Basics - Anfänger-Themen 6
D Vektoren Initialisieren Java Basics - Anfänger-Themen 1
D Boolean Array initialisieren Java Basics - Anfänger-Themen 4
T Mehrdimensionale Arrays mit geschachtelter for-Schleife initialisieren Java Basics - Anfänger-Themen 14
J Array ausserhalb der Methode initialisieren Java Basics - Anfänger-Themen 4
b1ck Integer initialisieren bei do-while-Schleife Java Basics - Anfänger-Themen 11
M Java Arrays mit Werten initialisieren Java Basics - Anfänger-Themen 3
K Wieso muss man finale statische Variablen sofort oder eben im Konstruktor initialisieren? Java Basics - Anfänger-Themen 2
V Tastatur initialisieren JFrame Probleme Java Basics - Anfänger-Themen 6
L Arrays richtig initialisieren Java Basics - Anfänger-Themen 1
W Klassen [GELÖST] Objekte während der Laufzeit mit neuen veränderten Werten beliebig oft initialisieren Java Basics - Anfänger-Themen 2
B Rekursion - Variable initialisieren Java Basics - Anfänger-Themen 2
T Variable deklarieren, ohne zu initialisieren... Java Basics - Anfänger-Themen 3
M Objekt Array an konstruktor übergeben und Initialisieren Java Basics - Anfänger-Themen 1
K Objekte im Konstruktor initialisieren Java Basics - Anfänger-Themen 3
CyberFish initialisieren, obwohl es gemacht wurde! Bitte um Hilfe Java Basics - Anfänger-Themen 10
K Array mit Double initialisieren Java Basics - Anfänger-Themen 10
J statische Methoden auf eine LinkedList initialisieren? Java Basics - Anfänger-Themen 5
B Frage zur Effizienz - alle Array-Felder initialisieren oder jedes Feld auf null prüfen? Java Basics - Anfänger-Themen 4
J StringBuilder initialisieren und Löschbefehl Java Basics - Anfänger-Themen 20
M Mehrdimensionales Array initialisieren Java Basics - Anfänger-Themen 3
DerGroßeNargus Doppelte Liste initialisieren Java Basics - Anfänger-Themen 2
R Sehr einfache möglichkeit ArrayList oder Array zu initialisieren? Java Basics - Anfänger-Themen 8
N Mit Kontrukor der Oberklasse lokale Variable initialisieren Java Basics - Anfänger-Themen 2
darekkay Datentypen HashSet bzw. LinkedList mit Werten initialisieren Java Basics - Anfänger-Themen 3
S Mehrdimensionales Char-Array initialisieren Java Basics - Anfänger-Themen 17
S mögliche Fehler beim Initialisieren von Variablen Java Basics - Anfänger-Themen 19
C Zweidimensionales String Array initialisieren Java Basics - Anfänger-Themen 2
D List<String[]> initialisieren Java Basics - Anfänger-Themen 4
D Problem mit Objekten Vererbung deklarieren initialisieren usw Java Basics - Anfänger-Themen 12
B Arrays initialisieren Java Basics - Anfänger-Themen 2
S Variable Initialisieren, aber wo? Java Basics - Anfänger-Themen 36
Y Array initialisieren, nach der Abfrage? Java Basics - Anfänger-Themen 3
K Datentypen Globale Variable direkt initialisieren oder im Konstruktor? Java Basics - Anfänger-Themen 13
N ARRAY initialisieren Java Basics - Anfänger-Themen 5
T Mehrere Variablen gleichzeitig initialisieren Java Basics - Anfänger-Themen 2
F Dreidimensionales Array? Wie initialisieren? Java Basics - Anfänger-Themen 5
Forlan OutputStream Initialisieren Java Basics - Anfänger-Themen 4
Ham Verhalten beim Initialisieren von Arrays Java Basics - Anfänger-Themen 16
N Initialisieren einer zufälligen Matrix Java Basics - Anfänger-Themen 12
A log4j - wie kann ich im Quellcode initialisieren statt in der properties-Datei? Java Basics - Anfänger-Themen 2
G Variablen initialisieren vor super() Java Basics - Anfänger-Themen 8
J ArrayLists initialisieren Java Basics - Anfänger-Themen 21
S Array initialisieren Java Basics - Anfänger-Themen 8
MQue ArrayList initialisieren Java Basics - Anfänger-Themen 17
G GUI in main Initialisieren Java Basics - Anfänger-Themen 15
M 2d string array initialisieren ohne neu String Java Basics - Anfänger-Themen 3
B Variable mit Methode initialisieren Java Basics - Anfänger-Themen 11
A char variable deklarieren und nicht initialisieren Java Basics - Anfänger-Themen 10
S statische variable initialisieren mit exception Java Basics - Anfänger-Themen 2
W Feld von boolean in main initialisieren. Java Basics - Anfänger-Themen 4
G Konstante im Konstruktur initialisieren Java Basics - Anfänger-Themen 8
G ArrayList initialisieren Java Basics - Anfänger-Themen 25
M Zweidimensionales String-Array initialisieren Java Basics - Anfänger-Themen 6
O String global initialisieren Java Basics - Anfänger-Themen 5
B ArrayList mit Startwerten initialisieren Java Basics - Anfänger-Themen 8
V Zweidimensionalen Array initialisieren Java Basics - Anfänger-Themen 3
G String Array initialisieren Java Basics - Anfänger-Themen 4
A String als Nullstring initialisieren Java Basics - Anfänger-Themen 2
F double[][] initialisieren Java Basics - Anfänger-Themen 9
G Arrays initialisieren Java Basics - Anfänger-Themen 8
M Wann ist initialisieren sinnvoll? Java Basics - Anfänger-Themen 4
G Wie Array initialisieren? Java Basics - Anfänger-Themen 10
H HashMap initialisieren<Key, Value>? Java Basics - Anfänger-Themen 9
N Feld initialisieren Java Basics - Anfänger-Themen 9
M 2-dimensionales Array initialisieren Java Basics - Anfänger-Themen 5
W 50 Variablen in Schleife initialisieren Java Basics - Anfänger-Themen 6
S String mit Konstruktor (per Übergabe) initialisieren Java Basics - Anfänger-Themen 10

Ähnliche Java Themen

Neue Themen


Oben