benötige non final - putExtra will final!

StefMa

StefMa

Dauergast
450
und wieder grüßt das Murmeltier ;)

In der Datenbank stehen Labels, die auf Buttons kommen und Zahlen, die beim Intent als putExtra übergeben werden.

PHP:
for(int i=0; i<howLong; i++)
    		{
                buttons[i] = new Button(this); 
                buttons[i].setText(lab);
                ll.addView(buttons[i], new LayoutParams(420, LayoutParams.WRAP_CONTENT));
                buttons[i].setOnClickListener(new View.OnClickListener()
                {
                	public void onClick(View v)
                	{
                		Intent myIntent = new Intent(v.getContext(), Internet.class);
                		myIntent.putExtra("internet", intnr);
                		startActivity(myIntent);
                	}
                });

                if(i != howLong-1)
                {
            		bttnLab.moveToNext();
            		lab = bttnLab.getString(0);
            		intNum.moveToNext();
            		intnr = intNum.getInt(0);
                }
    		}

intnr ist eine Zahl, die aus der Datenbank aus der entsprechenden ROW rausgelesen wird.
In der if() kann man gut sehen, wie ich dann zum nächsten ROW hüpfe und intnr eine neue Zahl bekommt.

Das Problem:
putExtra() möchte ein final! Allerdings ist final schelcht, wenn ich den wärt ändern möchte :flapper:

Hat dazu jemand eine Idee?!

MfG Ice
 
wenn du vorher einfach ne neue final var deklarierst?

final Integer tmp = new Integer(intr);

oder sowas in die richtung
 
  • Danke
Reaktionen: StefMa
IceClaw schrieb:
intnr ist eine Zahl, die aus der Datenbank aus der entsprechenden ROW rausgelesen wird.
In der if() kann man gut sehen, wie ich dann zum nächsten ROW hüpfe und intnr eine neue Zahl bekommt.

Das Problem:
putExtra() möchte ein final! Allerdings ist final schelcht, wenn ich den wärt ändern möchte :flapper:

Hat dazu jemand eine Idee?!

MfG Ice

Java lernen :flapper:

Deine anonyme innere Klasse braucht final weil sie sonst nicht weiß wie sie an den Wert kommen soll. Entweder das oder du definierst sie als Klassenvariable.
Eine Methode kann nicht verlangen eine final Variable zu bekommen. Das existiert nicht in Java.
 
Hallo,

wenn ich eine Klassenvariable
int intnr;
mache, dann wird immer das letzte was ich hinzugefügt habe als intnr zu JEDEM Button hinzugefügt! oO
Warum?

MfG Ice
 
Wenn du eine Instanzvariable (Klassenvariablen sind die mit static -- das nur zur Info) hast, wird der Wert genommen, denn diese Variable zum Zeitpunkt hat, wenn der Callback gerufen wird.

Wenn du in der Schleife (beim Erzeugen der Callbacks) immer wieder einen Wert an eine Variable zuweist, hat diese beim Aufruf der Callbacks natürlich den zuletzt zugewiesenen Wert.

In deinem Fall wäre wohl ein Array fällig. -- und etwas Java Nachhilfe, wie the_alien schon sagt :D
 
HI,

also danke erstmal für die Antworten!

Allerdings verstehe ich echt.. naja eigentlich kaum was oO
Ich habe Grundlagen in Java - etwas mehr vielleicht - deswegen frage ich ja auch...

Also nochmal zum mitschreiben:
alien sagt, ich soll eine Klassenvariable machen:
PHP:
static int intnr;
Wenn ich das mache, dann wird, wie ich schon geschrieben habe, nur immer die letzte ausgabe gemacht.

DieGoldeneMitte will, dass ich ein array mache, sähe also so aus??:
PHP:
static int[] intnr;

und dann entsprechend den rest intnr als array deklarieren..?
Dann bekomme ich aber beim catch() einen error (Selbstgeschreibenes Toast ;))

Also wie bitte soll ich das jetzt anstellen?

MfG Ice
 
was wäre, wenn du aus der inner class deines listeners eine "anständige" klasse baust

der gibst du dann den int paramter im construktor mit und setzt es dann in der onClick methode.
 
laß mal static weg und schreib private hin, dann sollte das klappen, oder google mal nach Klassenvariablen und Instanzvariablen in java.
 
IceClaw schrieb:
HI,

also danke erstmal für die Antworten!

Allerdings verstehe ich echt.. naja eigentlich kaum was oO
Ich habe Grundlagen in Java - etwas mehr vielleicht - deswegen frage ich ja auch...

Also nochmal zum mitschreiben:
alien sagt, ich soll eine Klassenvariable machen:
PHP:
static int intnr;
Wenn ich das mache, dann wird, wie ich schon geschrieben habe, nur immer die letzte ausgabe gemacht.

DieGoldeneMitte will, dass ich ein array mache, sähe also so aus??:
PHP:
static int[] intnr;

und dann entsprechend den rest intnr als array deklarieren..?
Dann bekomme ich aber beim catch() einen error (Selbstgeschreibenes Toast ;))

Also wie bitte soll ich das jetzt anstellen?

MfG Ice
Ich glaube du hast nicht verstanden wie innere anonyme Klassen arbeiten.
Lies dir den entsprechenden Part erst mal durch
Java ist auch eine Insel – 6.12 Innere Klassen
 
the_alien schrieb:
Deine anonyme innere Klasse braucht final weil sie sonst nicht weiß wie sie an den Wert kommen soll.

Da muss ich widersprechen^^
Dem Compiler/VM kann das eigentlich banane sein ob final oder nicht, es dient scheinbar lediglich dem Zweck, dass dem Programmierer bewusst ist, womit die innere Klasse arbeitet.

Beweis:
Code:
    public void fubar(long value){
        Button button = null;
        final long a = System.currentTimeMillis(); //blöde Konstantenoptimierung
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                fubar(a);
            }
        });
    }
disassembliert (teile ausgelassen):

Die Methode fubar()
Code:
# virtual methods
.method public fubar(J)V
    .locals 4
    .parameter "value"

    .prologue
    .line 8
    const/4 v2, 0x0

    .line 9
    .local v2, button:Landroid/widget/Button;
    invoke-static {}, Ljava/lang/System;->currentTimeMillis()J

    move-result-wide v0

    .line 10
    .local v0, a:J
    new-instance v3, Lde/tests/test2$1;

    invoke-direct {v3, p0, v0, v1}, Lde/tests/test2$1;-><init>(Lde/tests/test2;J)V

    invoke-virtual {v2, v3}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 15
    return-void
.end method
Und die vom Compiler erstellte innere Klasse
Code:
.class Lde/tests/test2$1;
# interfaces
.implements Landroid/view/View$OnClickListener;


# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
    value = Lde/tests/test2;->fubar(J)V
.end annotation

# instance fields
.field final synthetic this$0:Lde/tests/test2;

.field private final synthetic val$a:J

# direct methods
.method constructor <init>(Lde/tests/test2;J)V
    .locals 0
    .parameter
    .parameter

    .prologue
    .line 1
    iput-object p1, p0, Lde/tests/test2$1;->this$0:Lde/tests/test2;

    iput-wide p2, p0, Lde/tests/test2$1;->val$a:J

    .line 10
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V

    return-void
.end method


# virtual methods
.method public onClick(Landroid/view/View;)V
    .locals 3
    .parameter "v"

    .prologue
    .line 12
    iget-object v0, p0, Lde/tests/test2$1;->this$0:Lde/tests/test2;

    iget-wide v1, p0, Lde/tests/test2$1;->val$a:J

    invoke-virtual {v0, v1, v2}, Lde/tests/test2;->fubar(J)V

    .line 13
    return-void
.end method
Man kann sehr schön sehen, dass der Konstruktor geändert wird, und eine Kopie des Wertes bzw. bei Objekten die Referenz kopiert wird.
 
Ich sehe das so:

Das mit dem final ist eine Hilfe genau für Leute wie der OP, die noch nicht durchdrungen haben, dass der Code in einer anonymen Klasse nicht zeitlich zwischen dem Code davor und dahinter ausgeführt wird.

Eine nicht final Variable muss halt irgendwann "umkopiert" werden, weil der Scope der Definition beim Aufruf der anonymen Klasse in der Regel nicht mehr exisitert. Tja, und wann genau soll denn Kopiert werden? Das final macht daraus ein "egal wann, der Wert ändert sich ja eh nicht". :D
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: StefMa und the_alien
Fr4gg0r schrieb:
Da muss ich widersprechen^^
Dem Compiler/VM kann das eigentlich banane sein ob final oder nicht, es dient scheinbar lediglich dem Zweck, dass dem Programmierer bewusst ist, womit die innere Klasse arbeitet.

Ist richtig, aber es ist so spezifiziert und dem Compiler ist es nicht egal. Von daher sind das Spitzfindigkeiten und man kann an diesem Thread -und anderen in diesem und jedem anderen Java Forum- sehen, dass es wirklich gut ist, dass es so gemacht wurde.
Besser ein Fehler zur Compile- als ein Fehler zur Laufzeit.
 
  • Danke
Reaktionen: StefMa
Also so langsam fühle ich mich richtig schlecht in Java :/
Was habe ich denn da für ein Thema ausgegraben, in dem Worte vorkommen, die ich noch nie in meinem leben gehört habe :scared:

Btw: ich habs immer noch nicht hinbekommen und die verschiedenen Links zu "hilfeseiten" helfen mir auch nicht weiter...
 
Hallo

Ich würde das ganze so aufbauen (ungetestet):
PHP:
for(int i=0; i<howLong; i++) {
    buttons[i] = new Button(this);
    buttons[i].setText(lab);
    buttons[i].setId(intnr);
    ll.addView(buttons[i], new LayoutParams(420, LayoutParams.WRAP_CONTENT));
    
    buttons[i].setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            int intnr = v.getId();
            
            Intent myIntent = new Intent(v.getContext(), Internet.class);
            myIntent.putExtra("internet", intnr);
            startActivity(myIntent);
        }
    });

    [...]
}
Ich gebe dem Button eine ID. In diesem Fall benutze ich einfach den Wert, den du an deine neue Intent übergeben willst. Ich weiß zwar nicht, wo die Variable "intnr" deklariert wird, aber ich nehme mal an, du hast das VORHER gemacht.

Im OnClick-Event brauchst du jetzt nur noch die ID auszulesen und schon weißt du, welcher Button genau gedrückt wurde.
 
  • Danke
Reaktionen: StefMa
Ich finde bei Java sollte man schon wissen wie anonyme Klasse behandelt werden..
Um auch mal was sinnvolles beizutragen:
"Take away Lösung" ;)
final int tmpI = i; (das kommt natürlich vor setOnClickListener)
und dann intent.putExtra("internet", tmpI);
Ist prinzipiell das gleiche wie swordi geschrieben hat.
 
  • Danke
Reaktionen: StefMa
Öh lol! oO
Ich bin ein Vogel.. danke euch allen :D... (danke klicke werden gleich verteilt xD)

Mit Fr4gg0r bzw sowrdis hilfe hats geklappt!

Aber eine frage habe ich noch:
Wieso kann die Variable tmpl mehrmals deklariert werden?
Denn die schleife geht ja mehrmals durch.. also wird immer wieder final int tmp gesagt... Wie funktioniert dass den nu bitte?

MfG Ice
 
Die Variable existiert nur in der Schleife. Ist der Schleifendurchlauf beendet wird sie weggeworfen und danach eine neue erstellt.
 

Ähnliche Themen

T
Antworten
2
Aufrufe
1.154
t-ryder
T
F
Antworten
0
Aufrufe
1.229
FraSch1337
F
W
Antworten
1
Aufrufe
843
jogimuc
J
Zurück
Oben Unten