final und Variablen

Status
Nicht offen für weitere Antworten.
G

Guest

Gast
Gerade eben habe ich einen Artikel zu "Lucene with OJB" gelesen und dabei fallen mir
im Code des Authors ziemlich viele Variablen (innerhalb von Methoden) auf, die mit
final deklariert sind.
z.B.
Code:
public void add(final Student student) throws ServiceException {
  final Document doc = new Document();
  doc.add(Field.Text(NAME, student.getName()));
  doc.add(Field.Text(ID_NUMBER, student.getIdNumber()));
  doc.add(Field.Text(ADDRESS, student.getAddress()));
  doc.add(Field.Text(PHONE, student.getPhone()));
  doc.add(Field.UnIndexed(IDENTITY, student.getId().toString()));
  try {
    synchronized (mutex) {
      final IndexWriter writer = new IndexWriter(index, analyzer, false);
      writer.addDocument(doc);
      writer.optimize();
      writer.close();
    }
  }
  catch (IOException e) {
    throw new ServiceException("Unable to index student", e);
  }
}
In C++ war dieses Attribut immer dazu gedacht, Variablen bzw. Methodenargumente,
die "nicht verändert" werden, explizit zu kennzeichnen.
Dadurch war an manchen Stellen Pass-By-Reference unkritisch (statt Pass-By-Value).
Im obigen Code wird das Document-Objekt verändert, trotzdem ist es syntaktisch korrekt.

Was bringt dann "final" bei Methodenparametern bzw. lokalen Variablen innerhalb einer
Methode überhaupt, wenn diese trotzdem verändert werden?

Nur mal so ein Gedanke... :bahnhof:
 

Kaan

Bekanntes Mitglied
Final kannst du an mehreren Stellen verwenden:

1. Du kannst explizit vorschreiben, dass eine Methode nicht abgeleitet werden kann.

2. Du kannst auch Variablen um Objekt mit final kennzeichnen, damit sie als Konstanten angesehen werden und man ihnen nur EIN EINZIGES MAL in ihrer gesamten Lebensdauer einen Wert zuweisen kann.

Wenn du ein Objekt mit final versiehst kannst du es nur allgemein vor Zuweisungen schützen, aber nicht die einzelnen Elemente des Objekts. z.B. du kannst einem als final deklarierten Array-Objekt nur einmal eine neue Instanz zuweisen, aber du kannst jederzeit einzelne Array-Elemente verändern.

Bei deinem Beispiel wurde das Document Objekt als final deklariert, trotzdem kannst du einzelne Werte durch add verändern/ hinzufügen. (denke ich zumindest)
 
B

Beni

Gast
Öhm, bei dieser Methode? Nö, praktisch kein Unterschied ob mit oder ohne.

"final" kann man vorallem für Konstante Zahlenwerte brauchen (oder auch einfach Variablen, die nicht auf andere Referenzen zeigen dürfen).

Und dann gibts noch den Trick, Methodenvariablen anonymen Klassen sichtbar zu machen.

Aber mehr fällt mir auch nicht ein (in Bezug auf Variablen).
 

semi

Top Contributor
@Kaan & Beni
Klar, ich kenne die "typischen" Anwendungssfälle. Nur der Code des Authors machte mich etwas
nachdenklich. Irgendwie "Hab' ich was verpasst?" :wink:
Ich sehe eigentlich nur die folgende Anwendungen dafür.

Konstanten
Code:
public static final int CENTER = 1;
Methoden (entweder um das Überschreiben zu verhindern oder bestimmte Abläufe zu erzwingen; Typisch für Frameworks)
Code:
public final void doSomething() {
  preProcessing();
  reallyDoSomething();
  postProcessing();
}

protected abstract void reallyDoSomething();
Klasse (Klasse nicht mehr überschreibbar)
Code:
public final class Foo
Anonyme Klassen (hier wohl die häufigste Anwendung)
Code:
final JFrame frame = ....;
frame.addWindowListener(
  new WindowAdapter() {
    public void windowClosing(WindowEvent e) {
      frame...
    }
  }
);
Strings als Parameter an Methoden (Keine Kopie sondern Referenz; nur bei String sinnvoll?)
Code:
public void doSomething(final String s)
Gerade der letzte Fall ist die einzige mir bekannte Anwendung von final bei
Methodenparametern, die Sinn macht. Ohne final wird der String kopiert.
Mit final wird die Referenz übergeben. Alle anderen Objekte werden sowieso By-Reference
übergeben, daher macht es keinen Sinn.

Was meint Ihr?
 
S

stev.glasow

Gast
Nicht zu vergessen sind die 'privaten' Instanzvariablen die keinen Setter haben, die kann man eigentlich immer final setzen.
[edit] und natürlich soetwas:
Code:
public static final int TOP = 1;
public static final int BUTTOM = 2;
[edit]
achja
Code:
final FooBar fb = ...;
AClass ac = new AClass(){
    public void foo(){
          fb.bla();
    }
}
 
B

bygones

Gast
Anonymous hat gesagt.:
In C++ war dieses Attribut immer dazu gedacht, Variablen bzw. Methodenargumente,
die "nicht verändert" werden, explizit zu kennzeichnen.
Wenn die Variable nicht explizit für den Zugriff auf einen innere / anonyme Klasse benötigt wird halte ich das in Java für den Gleichen Zweck wie in C++ !
 

semi

Top Contributor
@deathbyaclown
Am besten zeige ich an einem Beispiel, was ich meine.

C++
Code:
class A {
  private:
    int value;
  public:
    A():value(0) {
    }
    void setValue(int v) {
      value=v;
    }
};

void test(const A a) {
  a.setValue(1);
}

int main() {
  A a;
  test(a);
  return 0;
}
Java
Code:
public class Final {
  static class A {
    private int value;
    public A() {
      value = 0;
    }
    public void setValue(int v) {
      value = v;
    }
  }

  private static void test(final A a) {
    a.setValue(1);
  }

  public static void main(String argv[]) {
    A a = new A();
    test(a);
  }
}
In C++ kriegst Du es wegen dem "const" nicht mal compiliert.
In Java wird's akzeptiert, ohne dass das "final" etwas bewirken würde.

Gruß,
Michael
 
B

bygones

Gast
danke semi, mir ist C++ mittlerweilen auch ein Begriff *g

ich weiß dass die beiden "final" unterschiedlich gewichten (siehe dein Bsp) - final Objekte in Java heißen nicht gleich das Objekt ist immer gleich (siee dein Bsp *g).... dennoch weißt du dass das Objekt "a" in deinem Bsp nie ein anderes Objekt der Klasse "A" sein kann, das neue zuweisen nämlcih geht nicht....

PS: ist gutes Bsp - ähnliches prinzip tritt auf bei final arrays... (habe mal nen FAQ beitrag dazu geschrieben)... wenns dir recht ist würde ich dein bsp da mitaufnehmen ?!
 

semi

Top Contributor
ich weiß dass die beiden "final" unterschiedlich gewichten (siehe dein Bsp) - final Objekte in Java heißen nicht gleich das Objekt ist immer gleich (siee dein Bsp *g).... dennoch weißt du dass das Objekt "a" in deinem Bsp nie ein anderes Objekt der Klasse "A" sein kann, das neue zuweisen nämlcih geht nicht....
Mit const in C++ sagt man, dass das Objekt nicht verändert wird. Ich meine nicht, dass man die Referenz des Objektes ändert. Dies wäre etwas ganz anderes (Referenzpointer) und ist in Java nicht möglich.
z.B.
Code:
#include <iostream.h>

class A {
  private:
    int value;
  public:
    A():value(0) {
    }
    void setValue(int v) {
      value=v;
    }
    int getValue() {
      return value;
    }
};

typedef A* PtrA;

void test(PtrA &a) { // & bedeutet Referenz eines Zeigers auf A
  a->setValue(2); // ursprüngliches Objekt ändern
  a = new A();      // der Referenz ein anderes Objekt zuweisen
}

int main() {

  PtrA a = new A(); // Eine Instanz von A erstellen
  PtrA b = a;       // diese auh dem anderen Zeiger zuweisen

  test(a); // Die Referenz! ändern

  // Die Zeiger zeigen auf unterschiedliche Objekte
  cout << a->getValue() << endl; // Ausgabe 0;
  cout << b->getValue() << endl; // Ausgabe 2; Dies ist das ursprüngliche Objekt

  return 0;
}
OK, Zeiger aus C++ vermisse ich aber nicht :bae::wink:

wenns dir recht ist würde ich dein bsp da mitaufnehmen ?!
Klar, mach' nur. :wink:

Gruß,
Michael
 

Bleiglanz

Gesperrter Benutzer
Gerade der letzte Fall ist die einzige mir bekannte Anwendung von final bei
Methodenparametern, die Sinn macht. Ohne final wird der String kopiert.
Mit final wird die Referenz übergeben. Alle anderen Objekte werden sowieso By-Reference
übergeben, daher macht es keinen Sinn.
Das ist falsch, es wird immer die Referenz übergeben. Der Sinn von final bei Methodenparametern ist nur, dass man sich beim programmieren selbst davor schützen möchte, übergebene Referenzen versehentlich zu ändern.
 

Isaac

Bekanntes Mitglied
checkstle, ein Plugin für Eclipse, zeigt dir Variablen an wenn diese nur initialisiert aber nie geändert werden und nicht final sind.

Final bringt in diesem Fall rein garnichts (also keine Performance oder sowas in der Art). Der Code liest sich einfacher wenn man weiss das diese Variable ihren Wert nie ändert.
 
G

Guest

Gast
@Bleiglanz
Stimmt nicht ganz. Strings werden immer kopiert, wenn man dies nicht mit final unterbindet.
Lass mal einen Debugger drüberlaufen, der die Adressen der Strings anzeigt, dann siehst
Du, was passiert.

Gruß,
Michael (semi)
 

Bleiglanz

Gesperrter Benutzer
@Gast

Versteh ich nicht??

Die Semantik von Objekten ist so, dass bei Funktionsaufrufen immer "die Referenz" übergeben wird (da braucht man gar nicht weiter drüber nachdenken)

Aber: es gibt sog. "immutable Objekte" (und da gehören Strings dazu, die werden noch dazu von der JVM besonders behandelt), die werden nicht "kopiert ", sondern bei jeder Änderung neu erzeugt [das ist was ganz anderes]

Frage: kannst du mir einen Aufruf konstruierenm in dem "false" rauskommt, wenn die Funktion mit identischen Argumenten foo(x,x) aufgerufen wird?
Code:
    public static void foo(String a, final String b)
    {
        System.out.println("a ist b: "+(a==b));
    }
 

semi

Top Contributor
@Bleiglanz
OK, meine letzte Antwort war Quatsch. Ich muss im Debugger irgendwie die Adressen
zweier Variablen verwechselt haben.

Das C++ Beispiel von mir ist ebenfalls nicht das gleiche wie in Java.
Vergleich Java-C++
Code:
void test(A a)       entspricht       void test(A* a)
void test(final A a) entspricht       void test(A* const a)
void test(final A a) entspricht NICHT void test(const A* a)

A a = new A(); entspricht       A *a = new A(); in C++
A a = new A(); entspricht NICHT A a; in C++

A a;
test(a);  // Ein Objekt A über den Stack übergeben
test(&a); // Referenz von A über den Stack übergeben

A *a = new A() ;
test(a);  // Referenz bzw. Zeiger auf A über den Stack übergeben (so passiert's in Java)
test(&a); // Referenz eines Zeigers auf A über den Stack übergeben
Kurz gesagt, Objekt auf Heap oder über den Stack, das war der Unterschied. :roll:

Eines bleibt aber ungeklärt. Was bringt final bei Methodenparametern?
(Much quack about nothing) ;)
 

Bleiglanz

Gesperrter Benutzer
Eines bleibt aber ungeklärt. Was bringt final bei Methodenparametern?
Der Sinn von final bei Methodenparametern ist nur, dass man sich beim programmieren selbst davor schützen möchte, übergebene Referenzen versehentlich zu ändern.
Viele Leute haben Methoden mit tausenden Zeilen (leider) und da ist es ganz praktisch, wenn man nicht irgendwo versehentlich ein übergebenes Argument überschreibt - das ist IMHO eine reine Complile-time Geschichte?
 

semi

Top Contributor
Yepp so ist es. Ich habe nicht daran gedacht, da ich grundsätzlich
nie einem Methodenparameter irgendwelche neuen Instanzen von
Objekten zugeweise.

Thema erledigt. :roll:

Gruß,
Michael
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
D Alle Variablen final setzen ? Allgemeine Java-Themen 26
V Wie funktioniert das Schlüsselwort "final" von Java? Allgemeine Java-Themen 19
G final "spammen" + bedeutung Allgemeine Java-Themen 14
J Final Method Allgemeine Java-Themen 9
I Java: public final Werte: Gute oder schlechte Praxis? Allgemeine Java-Themen 6
Neumi5694 Interpreter-Fehler final Eigenschaft während Laufzeit geändert Allgemeine Java-Themen 2
J private static final String variable Allgemeine Java-Themen 8
T Enumeration/Static Final/Bitfield Allgemeine Java-Themen 6
M final vor dem parameter eines Konstruktors Allgemeine Java-Themen 1
X Cannot refer to a non-final variable settings inside an inner class defined in a different method Allgemeine Java-Themen 4
G Synchronization on non final field Allgemeine Java-Themen 10
Z Als Final deklarierte Klasse im Array sortieren Allgemeine Java-Themen 2
G Klasse als final -> Laufzeitverbesserung? Allgemeine Java-Themen 4
T Final Methode dennoch überschreiben! Allgemeine Java-Themen 10
W Innere Klasse und final Allgemeine Java-Themen 11
A Als FINAL deklarieren -> sinnvoll? Allgemeine Java-Themen 16
S 2 Fragen allgemeine fragen zu final und interface Allgemeine Java-Themen 13
S Reflections und final Allgemeine Java-Themen 19
O does not declare a static final serialVersionUID field of . Allgemeine Java-Themen 6
meez immutable final? Allgemeine Java-Themen 23
S Wave Soundausgabe Java 1.4.2 contra 1.5 Final Allgemeine Java-Themen 27
B Java 5.0 Final Allgemeine Java-Themen 3
M 1.5 final? Allgemeine Java-Themen 2
C Erste Schritte Variablen in abhängigkeit von Git branch Allgemeine Java-Themen 7
Fabiator Variablen Variablen Zählen Allgemeine Java-Themen 3
S Mit Methoden kann man definieren für was <T> steht. Geht das auch irgendwie für Variablen? Allgemeine Java-Themen 12
berserkerdq2 Labels in IJVM sind keine lokalen Variablen oder? Allgemeine Java-Themen 2
O Fehler bei Variablen Allgemeine Java-Themen 2
N File Path mit Variablen angeben Allgemeine Java-Themen 1
nonickatall Methoden Kann man Klassen/Methoden aus Variablen heraus aufrufen? Allgemeine Java-Themen 6
R Geometry erstellen die abhängig von Variablen ist Allgemeine Java-Themen 6
O Formatierte String ausgabe bei vier Variablen in einer Zeile Allgemeine Java-Themen 1
P static Blocks und variablen Allgemeine Java-Themen 41
S Klassen Einfügen von unbekannter menge an Variablen in eine Klasse mithilfe von ASM Allgemeine Java-Themen 5
V Datentypen Graphikrechner 2/Strings und Variablen in Doubles umwandeln Allgemeine Java-Themen 6
S Kann man Variablen oder Felder definieren deren Typ zwei Interfaces ist..? Allgemeine Java-Themen 9
M Wie kann man eine void Methode mit Variablen von zwei verschiedenen Objekten ausführen? Allgemeine Java-Themen 15
B Übernommene Variablen(werte) aus der Main-Klasse ändern? Allgemeine Java-Themen 9
D BlueJ, Variablen die mehrfach vorkommen gleichzeitig umbenennen Allgemeine Java-Themen 3
C Variablen Variablen mit unendlichem Wert Allgemeine Java-Themen 22
J Variablen Mehrere int-variablen in txt abspeichern und danach wieder auslesen Allgemeine Java-Themen 1
T Maximale Felder maximale Variablen Allgemeine Java-Themen 2
W Lebendige Variablen herauslesen Allgemeine Java-Themen 1
K Summierung einer Variablen Allgemeine Java-Themen 5
B Gibt es eine Funktion die den Datentyp einer Variablen ermittelt? Allgemeine Java-Themen 8
X Threads Externe Variablen in Run Methoden verändern Allgemeine Java-Themen 4
Messoras Klassen Sämtliche Variablen einer Klasse übernehmen Allgemeine Java-Themen 6
K Static Variablen verbieten Allgemeine Java-Themen 10
I Problem beim Aufrufen, von Objektmethoden/ -variablen Allgemeine Java-Themen 6
J Text lesen und in Variablen speichern Allgemeine Java-Themen 3
A Best Practice Variablen vertauschen - Performance Allgemeine Java-Themen 1
F Variablen Variablen schachteln Allgemeine Java-Themen 6
7 6 int variablen vergleichen Allgemeine Java-Themen 34
C Threads Variablen in einem Thread Aktualisieren Allgemeine Java-Themen 17
M Variablen Variablen in Text einbinden Allgemeine Java-Themen 5
K Überschreiben von Variablen bei rekursivem Funktionsaufruf Allgemeine Java-Themen 2
R Übergreifende Variablen? Allgemeine Java-Themen 10
OnDemand Input/Output Variablen in Datei Speichern um sie wieder auszulesen Allgemeine Java-Themen 4
D Variablen zur Laufzeit global speichern (Registry Pattern?) Allgemeine Java-Themen 6
iB0T "goto" Befehl aus Batch in Java und Variablen wert immer wieder neu setzen Allgemeine Java-Themen 4
D ClassLoader für Variablen einer Klasse setzen Allgemeine Java-Themen 24
B Methoden Alle Methoden und Variablen aus Java-Dateien auslesen. Allgemeine Java-Themen 7
C Kapselung Warum graift man auf Variablen nur über Methoden und nich direkt zu? Allgemeine Java-Themen 10
C Classloading und statische Variablen Allgemeine Java-Themen 2
K Variablen speichern Allgemeine Java-Themen 2
S Variablen bei Aufruf zurücksetzen Allgemeine Java-Themen 4
faetzminator statische Variablen in Interface - Vererbung? Allgemeine Java-Themen 9
V Gibt es einen Variablen Cast? Allgemeine Java-Themen 8
K Mehrere JVMs die auf eine Klasse mit statischen Variablen zugreift Allgemeine Java-Themen 19
D Wann sollte ich statische Methoden und Variablen benutzen? Allgemeine Java-Themen 44
M Generische Methoden mit Java und globale Variablen Allgemeine Java-Themen 9
J Statische Variablen, Threadübergreifend. Allgemeine Java-Themen 4
E Variablen anderer Klassen auslesen (nur Name bekannt) Allgemeine Java-Themen 4
P Variablen in einer anderen Klasse auf Änderungen überwachen Allgemeine Java-Themen 12
V Typargument einer Variablen erfragen Allgemeine Java-Themen 4
B Rechnen mit mehreren Variablen Allgemeine Java-Themen 2
G Thread variablen Sichtbarkeit Allgemeine Java-Themen 15
J Java Pfad nicht mehr in Path Variablen??? Allgemeine Java-Themen 2
T Mit JNI finale Variablen überschreiben Allgemeine Java-Themen 14
T JNI -> auf Java-Variablen etc zugreifen Allgemeine Java-Themen 6
M Bezeichnung für Component-Variablen Allgemeine Java-Themen 6
M Variablen an Java-Programm übergeben Allgemeine Java-Themen 3
Airwolf89 dynamischer Zugriff auf Variablen/ Objekte Allgemeine Java-Themen 4
A Überschreibung von Variablen Allgemeine Java-Themen 3
A JavaCC: Variablen zaehlen Allgemeine Java-Themen 12
B globale und lokale Variablen Allgemeine Java-Themen 17
G referenz von variablen Allgemeine Java-Themen 9
O getRuntime().Exec() - Environment - Variablen setzen? Allgemeine Java-Themen 2
S XML-Parsing / public-Member-Variablen / Design-Frage Allgemeine Java-Themen 8
M Variablen Speicher wieder freigeben ? Allgemeine Java-Themen 9
N Variablen eines Objektes (instanz) in einen Array lesen Allgemeine Java-Themen 7
S In Subklasse auf private Variablen zugreifen Allgemeine Java-Themen 4
S Variablen und ihre Tücken. Allgemeine Java-Themen 7
C Binärbereich einer Variablen abfragen Allgemeine Java-Themen 8
J Zugriff auf den Namen einer Variablen Allgemeine Java-Themen 7
J Überschreiben von Variablen Allgemeine Java-Themen 3
C dynamische variablen Namen! Allgemeine Java-Themen 4
M Int und String Variablen verändern Allgemeine Java-Themen 10
H zwei Date Variablen überschreiben sich Allgemeine Java-Themen 2
G Taushen der Input variablen einer method Allgemeine Java-Themen 14

Ähnliche Java Themen

Neue Themen


Oben