Denkfehler bei Interfaces und Casts?

Status
Nicht offen für weitere Antworten.

Ice-Tea

Bekanntes Mitglied
Nach langer nichtstuherei :D hab ich mich mal wieder an mein Spiel gesetzt.
Ich versuche grade meine Raumschiffe und Waffensysteme etwas Modularer aufzubauen, um es später leichter zu erweitern.

Doch bekomme ich eine Exception die ich mir nicht ganz erklären kann.
Hier erstmal ein wenig Code:

Ein Testschiff: ( zu Testzwecken inkl. Main() )
Code:
package de.flamingbytes.starfighters.server.kampf.lib.ships;

import de.flamingbytes.starfighters.server.kampf.lib.weapons.*;
import java.util.Vector;


public class Nemesis {
    private String name = "Nemesis";
    private short sid = 15;
    
    private int fullAgK = 0;
    
    private Vector weaponSlots = new Vector();
    
    public static final byte slots = 16;
    /** Creates a new instance of Nemesis */
    public Nemesis() {
        this.weaponSlots.setSize(slots);
        this.weaponSlots.add(new SmallRockets());
        this.weaponSlots.add(new MediumRockets());
        this.getFullAgK();
    }
    
    public static void main(String[] args){
        new Nemesis();
    }
    
    public int getFullAgK(){
        this.fullAgK = 0;

        for(int i = 0; i < weaponSlots.size(); i++){
            Weapons w = (Weapons) this.weaponSlots.get(i);
            fullAgK += w.getAgk();
            System.out.print("Angriffskraft für Waffe ");
            System.out.print(w.getName() + ": ");
            System.out.println(w.getAgk());
        }
        System.out.print("AgK Gesamt:");
        System.out.println(fullAgK);
        return fullAgK;
    }
}

Das Waffeninterface:
Code:
package de.flamingbytes.starfighters.server.kampf.lib.weapons;

public interface Weapons {
    int getAgk();

    int getFireRate();

    int getMasse();

    String getName();

    int[] getPrice();

    byte getSlots();

    void setAgk(int agk);

    void setFireRate(int fireRate);

    void setMasse(int masse);

    void setName(String name);

    void setPrice(int[] price);

    void setSlots(byte slots);
    
}

Eine Waffe:
Code:
package de.flamingbytes.starfighters.server.kampf.lib.weapons;

public class SmallRockets implements Weapons {
    private String name = "Kleine Raketen";
    private int agk = 135;
    private int fireRate = 2;
    private int masse = 275;
    private byte slots = 2;
    /**
     * Metall, Kristall, Gas
     */
    private int[] price = {500, 0, 250 };
    
    /** Creates a new instance of SmallLaser */
    public SmallRockets() {
    }

    public int getAgk() {
        return agk;
    }

    public int getFireRate() {
        return fireRate;
    }

    public int getMasse() {
        return masse;
    }

    public String getName() {
        return name;
    }

    public int[] getPrice() {
        return price;
    }

    public byte getSlots() {
        return slots;
    }

    public void setAgk(int agk) {
        this.agk = agk;
    }

    public void setFireRate(int fireRate) {
        this.fireRate = fireRate;
    }

    public void setMasse(int masse) {
        this.masse = masse;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(int[] price) {
        this.price = price;
    }

    public void setSlots(byte slots) {
        this.slots = slots;
    }
}


Ich bekomme beim aufruf der 'nemesis' eine Nullpointerexception bei 'fullAgK += w.getAgk();'.
Code:
Exception in thread "main" java.lang.NullPointerException
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.getFullAgK(Nemesis.java:45)
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.<init>(Nemesis.java:32)
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.main(Nemesis.java:36)

Ich gehe davon aus das das Interface anstelle der eigenlichen Waffe gecastet wird. Das sollte natürlich nicht sein.
Kann ich das irgentwie umgehen? Bzw. wie löse ich das Problem am besten?

Bestem Dank im voraus
 

kleiner_held

Top Contributor
Das hat nix damit zu tun dass du da ein Interface verwendest.

Es lieg daran, dass du deinen leeren Vector auf die groesse 16 setzt (Zeile 19), damit enthaelt er 16 mal null und dann ueberschreibst du nur 2 Eintraege mit echten Weapons.

Deswegen dann eine NullPointerException, wenn du ueber alle Elemete iterierst.
 

Ice-Tea

Bekanntes Mitglied
Auch wenn es mir nicht ganz klar ist, es hat funktioniert.

Ich bin bischer davon ausgegeangen das java.util.Vector() ein Array mit erweiterten funktionen ist. Aber nach einigen versuchen schein es mir so als ob das nicht ganz korrekt ist.

Wenn ich ein Object[] mit 16 inhalten deklariere und die beiden ersten mit werten fülle sind 'nur' die folgenden 14 Null.
Warum also nicht beim Vector?

Außerdem ist mir aufgefallen das wenn ich setSize(16) am ende vom Konstruktor setze die Nullpointerexception zu unterschiedlichen Zeiten geworfen wird. Das würde bedeuten das Vector() Multithreaded ist.
Ist das Korrekt?
 

Murray

Top Contributor
Ice-Tea hat gesagt.:
Wenn ich ein Object[] mit 16 inhalten deklariere und die beiden ersten mit werten fülle sind 'nur' die folgenden 14 Null.
Warum also nicht beim Vector?

Außerdem ist mir aufgefallen das wenn ich setSize(16) am ende vom Konstruktor setze die Nullpointerexception zu unterschiedlichen Zeiten geworfen wird. Das würde bedeuten das Vector() Multithreaded ist.
Ist das Korrekt?

Mit Multithreading hat das nichts zu tun, und Vector#setSize ist auch nicht direkt mit der Deklaration eines Arrays vergleichbar. Vector#setSize sorgt dafür, dass der Vector nach dem Aufruf genau die Länge hat, die als Parameter übergeben wurde. Ist der Vector vor dem Aufruf bereits länger, dann werden die restlichen Elemente entfernt. Ist der Vector vorher kürzer, so wird er hinten mit "null"-Elementen aufgefüllt.

Bsp.:
Code:
Vector v = new Vector(); //--- V hat die Laenge 0
v.add( "a"); //--- V hat die Laenge 1
v.add( "b"); //--- V hat die Laenge 2
v.setSize( 5); //--- V hat die Laenge 5
Der Vector enthält jetzt {"a","b", null, null, null}

Anders sieht es aus, wenn man die Reihenfolge umdreht:
Code:
Vector v = new Vector(); //--- V hat die Laenge 0
v.setSize( 5); //--- V hat die Laenge 5
v.add( "a"); //--- V hat die Laenge 6
v.add( "b"); //--- V hat die Laenge 7
Der Vector enthält jetzt {null, null, null, null, null, "a","b"}

/EDIT: Code-Tag
 

Ice-Tea

Bekanntes Mitglied
Aber eklärt das immernoch nicht warum die Exception an verschiedenen stellen geworfen wird.

Hier zwei Beispielausgaben:
( setSize() steht hinter this.weaponSlots.add(new MediumRockets()); )

Code:
init:
deps-jar:
compile-single:
run-single:
Angriffskraft für Waffe Kleine Raketen: 135
Exception in thread "main" java.lang.NullPointerException
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.getFullAgK(Nemesis.java:45)
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.<init>(Nemesis.java:32)
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.main(Nemesis.java:36)
Angriffskraft für Waffe Mittlere Raketen: 155
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

Code:
init:
deps-jar:
compile-single:
run-single:
Angriffskraft für Waffe Kleine Raketen: 135
Angriffskraft für Waffe Mittlere Raketen: 155
Exception in thread "main" java.lang.NullPointerException
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.getFullAgK(Nemesis.java:45)
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.<init>(Nemesis.java:32)
        at de.flamingbytes.starfighters.server.kampf.lib.ships.Nemesis.main(Nemesis.java:36)
Java Result: 1
BUILD SUCCESSFUL (total time: 0 seconds)

Die einzige Erklärung die mir hierzu einfällt ist, das die JVM in einem seperatem Thread die Typen schon vor der Ausfürung prüft. Anders kann ich es mir nicht erklären.
 

Ice-Tea

Bekanntes Mitglied
Vector v = new Vector(); //--- V hat die Laenge 0
v.add( "a"); //--- V hat die Laenge 1
v.add( "b"); //--- V hat die Laenge 2
v.setSize( 5); //--- V hat die Laenge 5


Der Vector enthält jetzt {"a","b", null, null, null}

Anders sieht es aus, wenn man die Reihenfolge umdreht:
Vector v = new Vector(); //--- V hat die Laenge 0
v.setSize( 5); //--- V hat die Laenge 5
v.add( "a"); //--- V hat die Laenge 6
v.add( "b"); //--- V hat die Laenge 7


Ok, das erklärt einiges.

Was aber wenn im Beispiel 1 nachträglich vom Benutzer Elemente (Waffen) hinzugefügt werden? Dann würde der Vector wie im Beispiel 2 verlängert.
Muss ich zwingent die Position des neuen Elements angeben, wenn ich eine Verlängerung verhindern will?
 

kleiner_held

Top Contributor
Wenn du mit einer fest eingestellten Anzahlt von "Slots" arbeiten willst, würde ich sogar nur einen einfachen Array nehmen - ist übersichtlicher als ein Vector mit null Elementen.
 
G

Guest

Gast
So bin ich bischer vorgegangen. Da waren die Waffen auch fest zugeordnet.
Ich möchte aber erreichen das die Waffen sollen von dem Benutzer gelöschet und neue angebaut/ersetzt werden können.
Bei einem Array müsste ich also auch mit Nullwerten arbeiten.

Das lässt sich mit einem Vector leichter realisieren.

Ich werde einfach beim Kauf von neuen Waffen darauf achten müssen, das der Vector nicht größer ist als er darf.

Abgesehen fällt mir grad auf, das ich sowieso mal wieder absoluten schwachsinn gecoded hab.

Naja, absolut nicht, aber es fehlten einige wichtige methoden:
(Ich hab mal wieder viel gedacht und wenig geschrieben ;) )


Code:
    public byte getUsedSlots(){
        byte s = 0;
        for(int i = 0; i < weaponSlots.size(); i++){
            Weapon w = (Weapon) this.weaponSlots.get(i);
            if(w != null){
                s += w.getSlots();
            }
        }
        return s;
    }
    
    public boolean addWeapon(Weapon w){
        byte us = this.getUsedSlots();
        
        if( (us + w.getSlots()) <= SLOTS){
            this.weaponSlots.add(w);
            this.weaponSlots.setSize(weaponSlots.size());
            return true;
        }else{
            return false;
        }
    }

Ich denke das erkärt mein Vorhaben und warum ich einen Vector brauche ;)

Die slots stehen nämlich nicht für die Anzahl der Elemente im Vector, sondern vielmehr für die 'größe' der Waffen.
Denn auch die dicke Nemesis soll keine 16 Plasmawerfer tragen können.
Das wäre ein wenig unfair :lol:
 
G

Gast

Gast
mal nen kleiner vorschlag zur güte ^^

Code:
private final int maxWeapons;

public byte getUsedSlots() {
 return weaponSlots.size();
}

public boolean addWeapon(Weapon w) {
 if(weaponSlots.size() > maxWeapons)
  return false;
 weaponSlots.add(w);
 return true;
}
 

kleiner_held

Top Contributor
Ich wuerde die dann empfehlen statt einem Vector eine ArrayList zu verwenden - die Klasse ist aktueller als Vector aber ansonsten in der Benutzung aehnlich. Es gibt nur keine setSize() Methode, aber auf die Verwendung dieser Methode solltest du ja auch beim Vector verzichten.
 

Yzebär

Bekanntes Mitglied
Ich würde sogar eine eigene Klasse schreiben, die eine ArrayList kapselt. Dort kannst du dann auch festlegen unter welchen Bedingungen Waffen hinzugefügt oder gelöscht werden können.
 
G

Guest

Gast
OK, ArrayList gefällt mir.
Da fällt das Iterieren mit hasNext() und next() auch etwas leichter. Ging zwar mit der for schleife auch, aber hab ich dann weniger Tipparbeit :)
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Präkrement Denkfehler Allgemeine Java-Themen 18
J Denkfehler Rekursion Allgemeine Java-Themen 5
M Logikproblem bzw. Denkfehler Allgemeine Java-Themen 5
Thallius App-Sprache in der App ändern. Wo ist mein Denkfehler? Allgemeine Java-Themen 6
M Normalized Iteration count funktioniert nicht. Wo ist mien Denkfehler? Allgemeine Java-Themen 6
D Rot-Schwart-Baum denkfehler im code? Allgemeine Java-Themen 6
O NullPointerException (wohl Denkfehler) Allgemeine Java-Themen 5
Tandibur Denkfehler bei Pattern.matches? Allgemeine Java-Themen 3
C Bilder rotieren, Denkfehler in der Berechnung? Allgemeine Java-Themen 2
V Hm Denkfehler? oder was stimmt da nicht? Allgemeine Java-Themen 2
B Zugriff auf Methoden unter JNI (Denkfehler?) Allgemeine Java-Themen 6
R Lesen von Interfaces (Programm Vervollständigen) Allgemeine Java-Themen 10
S Interfaces Allgemeine Java-Themen 10
S Wenn eine Klasse zwei Interfaces mit derselben Methodensignatur implementiert: welche wird aufgerufen? Allgemeine Java-Themen 15
S Kann man Variablen oder Felder definieren deren Typ zwei Interfaces ist..? Allgemeine Java-Themen 9
J Problem beim Generischen Klassen und Interfaces Allgemeine Java-Themen 2
S Kann ich eine Methode schreiben die alle Arten von funktionalen Interfaces akzeptiert..? Allgemeine Java-Themen 21
Stonie Prüfen von direkter Implementierung eines Interfaces Allgemeine Java-Themen 7
rentasad Design-Frage - Interfaces, Klassen, statische Methoden Allgemeine Java-Themen 3
J Generische Interfaces mehrfach einbinden Allgemeine Java-Themen 11
P Interfaces Allgemeine Java-Themen 1
K Wohin mit Interfaces? Allgemeine Java-Themen 2
J Interface Wofür Interfaces in Java verwenden? Allgemeine Java-Themen 3
F Namen des Interfaces ausgeben Allgemeine Java-Themen 1
P ClassCastException bei Verwendung eines Interfaces Allgemeine Java-Themen 7
F Sinn des Serializable Interfaces Allgemeine Java-Themen 8
G Interface Laden der Konfiguration über Interfaces sinnvoll? Allgemeine Java-Themen 28
X Generic muss zwei Klassen/Interfaces erfüllen Allgemeine Java-Themen 5
K Objekt einer konkreten Implementierung eines Interfaces durch übergebenen String Allgemeine Java-Themen 2
D Java Interfaces Allgemeine Java-Themen 3
sylo toString() Methode eines Interfaces überladen. Allgemeine Java-Themen 17
S statische Interfaces..? Allgemeine Java-Themen 6
M Frage zu Interfaces (Beispiel: Comparable) Allgemeine Java-Themen 13
I Interfaces und abstrakte Methoden Allgemeine Java-Themen 5
C Verständnis zur Strukturierung von Java-Projekten/Interfaces Allgemeine Java-Themen 2
M Methodenaufrufe sind über Interfaces langsamer. Allgemeine Java-Themen 43
J Verständnisfrage zu Casts auf Interfaces Allgemeine Java-Themen 5
J Statische Methoden in Interfaces? Allgemeine Java-Themen 10
J Immutable mit Interfaces möglich? Allgemeine Java-Themen 2
G verzweiflung pur mit java interfaces Allgemeine Java-Themen 5
M Bereits imlplementierte Interfaces nochmal bei "impleme Allgemeine Java-Themen 10
T Nochmal Frage zu Vererbung Interfaces etc. Allgemeine Java-Themen 10
F Implementierte Interfaces ermitteln Allgemeine Java-Themen 6
T JDBC: Unterschiede in Interfaces zwischen 2 Java-Versionen. Allgemeine Java-Themen 6
E Attribute in Interfaces möglich? Allgemeine Java-Themen 17
M 2 Java-Interfaces öffnen in Unix Allgemeine Java-Themen 4
B "Instantiieren" eines Objekts eines Interfaces Allgemeine Java-Themen 10
F Problem: mehrere Interfaces definieren equals() neu Allgemeine Java-Themen 24
F Probleme mit Interfaces Allgemeine Java-Themen 3
L Verschiedene Versionen eines Interfaces Allgemeine Java-Themen 12
S Methoden aus Interfaces mit unterschiedlichen Parametertypen Allgemeine Java-Themen 7
deetee Wie nennt man Interfaces wie Serializable? Allgemeine Java-Themen 8
B Elegantere Lösung bei der Implementierung eines Interfaces Allgemeine Java-Themen 2
N 2 Interfaces mit Methoden selber Signatur implementieren Allgemeine Java-Themen 5
D Implementierungen eines Interfaces finden Allgemeine Java-Themen 9
T Generics, Enumerations und Type-Casts Allgemeine Java-Themen 13

Ähnliche Java Themen

Neue Themen


Oben