MichiLee: Objekt in Long, String oder Integer parsen

Hallo Forum

ich habe eine Hashtable:
Hashtable<String, Vector<Object>> hashData;

In dem Vector<Object> sind dann meistens Strings drin, auch aber manchmal Datum oder Zahlen.

Ich lese die HashData meist dann so aus:

String tmp = ((String)hashData.get("key").elementAt(0));
Ich erhalte das Objekt an der Stelle 0 vom ObjectVector und caste es in ein String. Funktioniert prima.

String tmp= String birthday =((String)hashData.get("birthday").elementAt(i).toString());
Wenn in dem Object ein Geburtstag drin ist (Was von der Datenbank kam 1980-01-01) muss ich hinten ein toString() anhängen.
Jetzt frage ich mich warum, bzw. was als erstes greift, das toString() hinten oder das Casten vorne?

int tmp = ((Long)hashData.get("key").elementAt(i)).intValue();
Wenn ich nun in dem Object eine Zahl drin habe, geht nur das obere Konstrukt, aber   ((Integer)hashData.get("key").elementAt(i)).intValue() geht nicht? (Das irritiert mich auch einwenig. In meinem Beispiel ist da eine 1 drin.

int tmp = Integer.parseInt((String)hashData.get("key").elementAt(0));
ging auch nicht, obwohl da eine 1 drin ist.

Viele Grüße

  1. Ich sammle gerade noch ein Paar Erkentnisse.

    In dem Vector der Hashtable sind nur Objecte.
    die Objecte hatte ich davor von der Datenbank ausgelesen und gefüllt, indem die Datasourceklasse einfach die Ergebnisse in den Vector added:

    while(rs.next()){  
       while (i <= rs.getMetaData().getColumnCount()) {  
          data.add(rs.getObject(i));  
          i++;  
       }  
    ....
    
    public void add(Object data){  
       this.data.add(data);  
       count++;  
    }
    

    Beim auslesen der Hashdate, bzw. des Vector macht es aber ein Unterschied ob ich (Long) oder <Integer> schreibe, denn in der Datenbank hab ich ID als Long definiert und Sex als Int.

    int id = ((Long)hashData.get("id").elementAt(i)).intValue();
    int sex = ((Integer)hashData.get("sex").elementAt(i)).intValue();

    Das irritiert mich weiterhin, da ich alles als Object reingetan hatte in den Vector.

    1. [...]
      Das irritiert mich weiterhin, da ich alles als Object reingetan hatte in den Vector.

      Das braucht Dich nicht zu irritieren. Du "tust" die Instanzen nicht als Object in den Vector, sondern Du triffst keine weiteren Einschränkungen, als dass es Objekte sind. Wenn Du eine Tasche hast (Achtung, Real World Beispiel), und Du definierst, dass in diese Tasche Objekte reingetan werden dürfen, dann kannst Du in diese Tasche eine Banane und eine Handgranate stecken. Beides sind Objekte. Sie werden aber durch das reintun nicht zu irgendeinem abstrakten "Object", sondern bleiben Banane und Handgranate. Nur beim rausholen musst Du selbst aufpassen, bei welchem Objekt Du an der angefügten Lasche ziehst. ;)
      Die Typangabe bei einer Collection sagt aus, dass Objekte dieses Typs und spezialisierter Untertypen in die Collection gepackt werden dürfen. Da alles ein Spezialtyp von Object ist, kann alles in die Collection gepackt werden. Es behält aber seinen Spezialtyp und muss beim rausholen auf diesen gecastet werden, wenn spezielle Methoden (also nicht von Object" definert) verwendet werden sollen.

      Peter

      1. Hi Peter,

        Das braucht Dich nicht zu irritieren. Du "tust" die Instanzen nicht als Object in den Vector, sondern Du triffst keine weiteren Einschränkungen, als dass es Objekte sind. Wenn Du eine Tasche hast (Achtung, Real World Beispiel), und Du definierst, dass in diese Tasche Objekte reingetan werden dürfen, dann kannst Du in diese Tasche eine Banane und eine Handgranate stecken. Beides sind Objekte. Sie werden aber durch das reintun nicht zu irgendeinem abstrakten "Object", sondern bleiben Banane und Handgranate. Nur beim rausholen musst Du selbst aufpassen, bei welchem Objekt Du an der angefügten Lasche ziehst. ;)
        Die Typangabe bei einer Collection sagt aus, dass Objekte dieses Typs und spezialisierter Untertypen in die Collection gepackt werden dürfen. Da alles ein Spezialtyp von Object ist, kann alles in die Collection gepackt werden. Es behält aber seinen Spezialtyp und muss beim rausholen auf diesen gecastet werden, wenn spezielle Methoden (also nicht von Object" definert) verwendet werden sollen.

        das hast du wie immer mal wieder sehr schön erklärt. Nochmals vielen Dank. Ich kriege auch schon ein schlechtes Gewissen, wenn ich so viel Frage und Leute für mich Zeit opfern müssen. Hoffentlich werde ich aber auch mal zum Checker und kann anderen helfen.

        Kurz nochmal zur Thematik.
        Ich dachte wie gesagt, dass folgende Methode zum Auslesen aus der Datenbank alles als striktes Objekt holt:

        while (i <= rs.getMetaData().getColumnCount()) {
        data.add(rs.getObject(i));

        Vor allem, weil rs. ja auch Methoden hat, wo es verschiedene andere Typen zurückgeben könnte.

        int count=((Long)hashData.get("count(*)").elementAt(0)).intValue();

        Mir ist auch aufgefallen, dass ich bei einem count(*) das Objekt auch in ein Long casten muss, damit es funktioniert, ein Integer geht nicht. Auch interessant zu wissen.

        Wie ich von Deinem Vorbeitrag herausgelesen habe, kann ich ja nur beim Casten den Typ angeben. Dann ist mir im vorherhigen Beitrag das mit Long und Integer klar. (Eigentlich bräuchte ich dann das intValue() garnicht extra aufrufen, wenn es eh ein Zahlenobject ist und ich richtig Caste). Bei Birthday hab ich aber noch ein kleines Problem:

        String tmp= String birthday =((String)hashData.get("birthday").elementAt(i)).toString();

        In der Datenbank ist es als Date angegeben, dann sollte doch das Casten in (String) auch nicht möglich sein. Laut der Klammerung (verändert) sollte er aber erst Casten und auf das ermittelte Objekt die Methode toString() anwenden

        Viele Grüße und einen schönen Abend noch
        Michi

        1. Guten Morgen!

          [...] Ich kriege auch schon ein schlechtes Gewissen, wenn ich so viel Frage und Leute für mich Zeit opfern müssen. Hoffentlich werde ich aber auch mal zum Checker und kann anderen helfen.

          Du brauchst kein schlechtes Gewissen haben. Jeder, der hier hilft, macht das gerne. Bei mir sind es einfach meine kleinen Pausen, wenn ich kurz etwas anderes sehen will, als meine IDE. :)

          [...]
          Ich dachte wie gesagt, dass folgende Methode zum Auslesen aus der Datenbank alles als striktes Objekt holt:
          [...]
          Vor allem, weil rs. ja auch Methoden hat, wo es verschiedene andere Typen zurückgeben könnte.

          Das ResultSet schaut bei der allgemeinen Methode getObject() einfach nicht nach, was es in der Hand hat (es greift also in die Tasche und zieht das gewünschte Objekt raus, interessiert sich aber nicht dafür, ob es Banane oder Handgranate ist). Das Objekt selbst hat aber einen konkreten Typ. Nämlich den, der beim reinlegen in das ResultSet vergeben wurde (hängt vom Datenbankspaltentyp und dem JDBC-Treiber (dem DBMS) ab.

          [...]
          Mir ist auch aufgefallen, dass ich bei einem count(*) das Objekt auch in ein Long casten muss, damit es funktioniert, ein Integer geht nicht. Auch interessant zu wissen.

          Das hängt auch wieder vom JDBC-Treiber ab. Der eine legt das Ergebnis eines count in einem Integer ab, der andere in einem Long. Wobei Long in meinen Augen weiterverbreitet ist.

          [...] Bei Birthday hab ich aber noch ein kleines Problem:

          String tmp= String birthday =((String)hashData.get("birthday").elementAt(i)).toString();

          In der Datenbank ist es als Date angegeben, dann sollte doch das Casten in (String) auch nicht möglich sein. Laut der Klammerung (verändert) sollte er aber erst Casten und auf das ermittelte Objekt die Methode toString() anwenden

          Laut der o.a. Klammersetzung wird aus hashData das Objekt mit dem Schlüssel "birthday" ermittelt, darauf die Methode elementAt(i) aufgerufen, danach gecastet, und dann toString() aufgerufen. Das heißt, das, was bei elementAt(i) zurückkommt, ist ein String, sonst würde der Cast nicht funktionieren. Das abschließende toString() ist allerdings obsolet, weil Du ja schon einen String hast.

          Schöne Grüße,

          Peter

  2. Hallo MichiLee,

    [...]
    String tmp= String birthday =((String)hashData.get("birthday").elementAt(i).toString());
    Wenn in dem Object ein Geburtstag drin ist (Was von der Datenbank kam 1980-01-01) muss ich hinten ein toString() anhängen.
    Jetzt frage ich mich warum, bzw. was als erstes greift, das toString() hinten oder das Casten vorne?

    Das Objekt wird ermittelt, die toString()-Methode wird aufgerufen, und dann wird gecastet. Anders könnte es auch nicht gehen, weil Du z.B. ein java.util.Date nicht auf String casten kannst.

    [...]
    int tmp = ((Long)hashData.get("key").elementAt(i)).intValue();
    Wenn ich nun in dem Object eine Zahl drin habe, geht nur das obere Konstrukt, aber   ((Integer)hashData.get("key").elementAt(i)).intValue() geht nicht? (Das irritiert mich auch einwenig. In meinem Beispiel ist da eine 1 drin.

    Das liegt daran, dass man ein Long nicht auf Integer casten kann und Integer nicht auf Long. casten heißt ja immer, ich gebe den genauen Typ eines Objekts an. Wenn ein Objekt aber diesen Typ nicht hat, dann kann ich ihn dafür auch nicht angeben (ein Long ist kein Integer, das sieht man anhand der Vererbungshierarchie, weil sie beide von Object erben).

    [...]
    int tmp = Integer.parseInt((String)hashData.get("key").elementAt(0));
    ging auch nicht, obwohl da eine 1 drin ist.

    Was "ging" da nicht? Du versuchst, das Objekt am Index 0 des Vectors mit dem Schlüssel "key" als String zu casten. Ist es ein String? Dann geht das. Danach willst Du den String als int parsen. Wenn es ein String ist, dann geht das. Ich vermute, Du hast in dem Vector keinen String, sondern ein Zahlobjekt (z.B. Integer oder Long).

    Schöne Grüße,

    Peter