AWT local variable * is accessed from within inner class; needs to be declared final

Hallo erstmal,

also folgendes Problem, ich schreibe gerade an einem kleinen Tool für unseren Clan bei World of Tanks wobei es darum geht bestimmten Panzern eine "Panzerauszeit" zu geben.
Ein User hat mehrere Panzer, das funktioniert auch alles ohne probleme, die Datenbankmethoden laufen über ein PHP-Backend(jpmdbc), das funktioniert alles soweit. So nun wollte ich, wenn ein User sich einloggt, dass er seine Tanks aufgelistet bekommt und daneben einen Button "Sperren" bekommt, dort hakt es jetzt.

Java:
         int ANZ = DBHandlers.getAnzTank(GamerObj.getID());
         Tank TankObj[] = DBHandlers.getTanks(GamerObj.getID());
         Label textTankID[] = new Label[ANZ];
         Label textTankName[] = new Label[ANZ];
         Label textTankBlocked[] = new Label[ANZ];
         Button blockButton[] = new Button[ANZ];
         
         Label textPanzerID = new Label();
         textPanzerID.setBounds(0, 25, 55, 13);
         textPanzerID.setText("PanzerID");
         textPanzerID.setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
         cp.add(textPanzerID);
         
         Label textPanzerName = new Label();
         textPanzerName.setBounds(60, 25, 55, 13);
         textPanzerName.setText("Name");
         textPanzerName.setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
         cp.add(textPanzerName);
         
         Label textBlocked = new Label();
         textBlocked.setBounds(120, 25, 65, 13);
         textBlocked.setText("Geblockt?");
         textBlocked.setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
         cp.add(textBlocked);

         for(int i = 0;i<ANZ;i++)
         {
           textTankID[i] = new Label();
           textTankID[i].setBounds(0, (40+i*18), 55, 13);
           textTankID[i].setText("" + TankObj[i].getTankID());
           textTankID[i].setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
           cp.add(textTankID[i]);
           textTankName[i] = new Label();
           textTankName[i].setBounds(60, (40+i*18), 50, 13);
           textTankName[i].setText("" + TankObj[i].getTankname());
           textTankName[i].setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
           cp.add(textTankName[i]);
           textTankBlocked[i] = new Label();
           textTankBlocked[i].setBounds(120, (40+i*18), 50, 13);
           if(timestamp_now > (long)TankObj[i].getBlockedUntil())
           {
             textTankBlocked[i].setText("Nein");
           }else{
             textTankBlocked[i].setText("Ja");
           }
           textTankBlocked[i].setFont(new Font("MS Sans Serif", Font.PLAIN, 13));
           cp.add(textTankBlocked[i]);
           blockButton[i].setBounds(175, (40+i*18), 50, 13);
           blockButton[i].setLabel("Block");
           blockButton[i].addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent evt) {
               blockButton_ActionPerformed(evt, TankObj[i].getUserID(), TankObj[i].getTankID());
             }
           });
           cp.add(blockButton[i]);
später kommt noch ein validate();...

und dann halt
Java:
  public void blockButton_ActionPerformed(ActionEvent evt, int userid, int tankid){
  DBHandlers.blockTank(userid, tankid);
  }

Fehler:
Tool.java:138:49: local variable TankObj is accessed from within inner class; needs to be declared final
blockButton_ActionPerformed(evt, TankObj.getUserID(), TankObj.getTankID());
^
Tool.java:138:57: local variable i is accessed from within inner class; needs to be declared final
blockButton_ActionPerformed(evt, TankObj.getUserID(), TankObj.getTankID());
^
Tool.java:138:73: local variable TankObj is accessed from within inner class; needs to be declared final
blockButton_ActionPerformed(evt, TankObj.getUserID(), TankObj.getTankID());
^
Tool.java:138:81: local variable i is accessed from within inner class; needs to be declared final
blockButton_ActionPerformed(evt, TankObj.getUserID(), TankObj.getTankID());

ich wüsste nicht, wie ich i als final deklarieren sollte 😉 geschweige denn die anderen Sachen.

Grüße

Unkaputtbar
 
Zuletzt bearbeitet:
schreib dir ne Methode doBlockBtn(){...} oder so und hol dir dort die Daten.
Ich halte nicht viel vom finalisieren von Variablen, um sie in einer anonymen ActionListenerinstanz zu benutzen. Dann kannst du in der actionPerformed(); einfach doBloclkBtn(); aufrufen und hast keine Probleme.

Gruß Vanny
 
Bei den meisten kann man "final" einfach hinschreiben, für das i kann man sowas machen wie
Java:
for(int ii = 0;ii<ANZ;ii++)
{
    final int i = ii;
    ... Rest wie vorher...

Aber die Struktur mit den Arrays und so sieht ziemlich unübersichtlich aus... Warum eingentlich AWT (Label, Button) und nicht Swing (JLabel, JButton) ...?

Wichtiger: Könnte man die Dinge, die da offenbar zusammengehören
Java:
        Label textTankID[] = new Label[ANZ];
         Label textTankName[] = new Label[ANZ];
         Label textTankBlocked[] = new Label[ANZ];
         Button blockButton[] = new Button[ANZ];
nicht zu sowas machen wie
Java:
class TankPanel extends JPanel
{
    private JLabel textTankId 
    ...

    public TankPanel()
    {
        setLayout(irgendeinPassendes);
        add(textTankId);
        ...
    }
    public void setTankID(int id)
    {
        textTankId.setText(String.valueOf(id));
    }
    ...
}
? Nur ein Gedanke....
 
Bei den meisten kann man "final" einfach hinschreiben, für das i kann man sowas machen wie
Java:
for(int ii = 0;ii<ANZ;ii++)
{
    final int i = ii;
    ... Rest wie vorher...

Aber die Struktur mit den Arrays und so sieht ziemlich unübersichtlich aus... Warum eingentlich AWT (Label, Button) und nicht Swing (JLabel, JButton) ...?

Wichtiger: Könnte man die Dinge, die da offenbar zusammengehören
Java:
        Label textTankID[] = new Label[ANZ];
         Label textTankName[] = new Label[ANZ];
         Label textTankBlocked[] = new Label[ANZ];
         Button blockButton[] = new Button[ANZ];
nicht zu sowas machen wie
Java:
class TankPanel extends JPanel
{
    private JLabel textTankId 
    ...

    public TankPanel()
    {
        setLayout(irgendeinPassendes);
        add(textTankId);
        ...
    }
    public void setTankID(int id)
    {
        textTankId.setText(String.valueOf(id));
    }
    ...
}
? Nur ein Gedanke....

Zum ersten mit dem final int i = ii; oder halt final int ii = i; hab ich mal so gemacht:
Java:
final Tank TankObjFinal = new Tank(TankObj[i].getUserID(), TankObj[i].getTankID());
//bzw. final Tank TankObjFinal = TankObj[i];
blockButton[i].addActionListener(new ActionListener() {
             public void actionPerformed(ActionEvent evt) {
               blockButton_ActionPerformed(evt, TankObjFinal.getUserID(), TankObjFinal.getTankID());
             }
           });
Das geht auch gut, jedenfalls meckert der Compiler nicht mehr, allerdings beim ausführen ->NullPointerException, was wohl an den blockButton hängt, auch beim 1. Durchlauf schon, also wo i=0 ist, hmmm eigentlich sollte es aber auch davon Möglich sein ObjektArrays zu erstellen ???:L
oder hängt das damit zusammen, das ja durch
Java:
             public void actionPerformed(ActionEvent evt) {
               blockButton_ActionPerformed(evt, TankObjFinal.getUserID(), TankObjFinal.getTankID());
             }
Eine Methode überschrieben wird und TankObjFinal in dieser Methode nicht bekannt ist? aber dann müsste doch eigentlich der Compiler schon meckern.

Das mit dem Swing wird dann wahrscheinlich auch mein NullPointerException Problem lösen, nehm ich mal an, ich werds mir mal genauer anschauen, vielleicht bau ich die GUI dann nochmal ein bisschen um.

Und zu dem letzten, das werd ich mir auch nochmal genauer anschauen, ich bin aber mehr der funktionale Typ, hauptsache es funktioniert 😉 bin aber auch noch ein relativer Javaneuling.



@Vanny das habe ich auch probiert, allerdings ohne Erfolg, bleibt bei dem selben Fehler.
 
blockButton ist sicherlich null wenn nirgendwo 'new Button()' steht, richtig,
besteht sonst noch eine Frage?

TankObjFinal ist offensichtlich bekannt, die Variante
> final Tank TankObjFinal = TankObj;
übrigens wohl doch sehr zu bevorzugen
 
blockButton ist sicherlich null wenn nirgendwo 'new Button()' steht, richtig,
besteht sonst noch eine Frage?

TankObjFinal ist offensichtlich bekannt, die Variante
> final Tank TankObjFinal = TankObj;
übrigens wohl doch sehr zu bevorzugen


Oh man, *ditsch* ok, ja ich bin doof. Nein, damit hat sich dann alles erledigt 😉

Ja, so hatte ich es zum Schluss auch drin.

Vielen Dank für eure Hilfe 🙂
 
äh, und Variablen natürlich noch unbedingt klein schreiben!
auch finale, außer statische Konstanten
 

Neue Themen


Zurück
Oben