Bessere Performance durch final: wann denn überhaupt?

nossek

Aktives Mitglied
Guten Abend,

es ist ja hier schon häufiger diskutiert worden, (und an anderen Stellen wird es häufig behauptet) dass eine Verwendung von final (für Klassen, Methoden, Variabeln oder Argumente) unter Umständen Performance verbessert.

Ich bin gard ziemlich viel am rumtesten was Performance angeht. Und habe noch nie einen Fall gefunden, wo "final" irgendwas gebracht hat.

Kann mir vielleicht jemand einen Fall umschreiben, wo das was bringt?

Danke, Gruß

nossek
 

Marco13

Top Contributor
Viel spannender fände ich persönlich jetzt wie du das getestet hast (oder getestet zu haben glaubst :bae: ).

Ob und wann es wirklich verläßlich messbar etwas bringt... das ist mit vielen "wenn"s und "aber"s versehen. Üblicherweise wird 'final' auch weniger für Optimierungen empfohlen, sondern eher weil es teilweise als "guter Stil" angesehen wird. (Das kann an manchen Stellen zutreffen, und ich habe mir das standardmäßige "private final" schon fast angewöhnt, aber bei Methodenparametern konnte ich mich noch nicht (systematisch) dazu durchringen...).

Am ehesten könnte ich mir wirklich messbare Auswirkungen noch bei vielen (vielen, vielen, vielen) Aufrufen von public-Methoden einer finalen/nicht finalen Klasse vorstellen, aber ... an den meisten Stellen ist der Bytecode, der entsteht, unabhängig vom "final"... und da könnte dann auch nichtmal der JIT das "final" ausnutzen...
 

Marco13

Top Contributor
Hmnaja :) Achte mal drauf, bei wie vielen Fields du "final" dazuschreiben könntest - es sind mehr, als man im ersten Moment denken würde (schon allein die meisten Collections, und alles was einmal im Konstruktor übergeben wird). Es gibt ja auch das Mantra: "Minimize Mutability", und wenn man versucht, dem zu folgen, ergeben sich häufige 'final's fast von allein. Tatsächlich denke ich, dass die ALLERmeisten Fehler in Programmen nicht mit falsch implementierten Algorithmen oder so zusammenhängen, sondern direkt mit einem fehlerhaften Zustand zu tun haben. Multithreading (was immer wichtiger wird) verstärkt dieses Problem nochmal überproportional.

EDIT: Aber natürlich gibt es "manchmal" immernoch setter und damit auch nicht-finale private Variablen
 

nossek

Aktives Mitglied
Viel spannender fände ich persönlich jetzt wie du das getestet hast (oder getestet zu haben glaubst ).

Uh, den ganzen code kann ich hier nicht posten, verwende etliche eigene Klassen...

Mal so grob ein Beispiel:

habe zB eine Klasse NumberUtil, nur mit statischen Methoden.

eine Methode heisst
Java:
public static double map(double value, double isMin, double isMax, double targetBoundary1, double targetBoundary2)
die skaliert einen Wert aus einem gegebenen Wertebereich [isMin-isMax] auf einen gewünschten Wertebereich [targetBoundary1-targetBoundary2].

dann eine Klasse ArrayUtil, in der die entsprechende Methode...
Java:
public static double[] mapArray(double[] array, double isMin, double isMax, double targetBoundary1, double targetBoundary2)
... map(...) auf ein array anwendet - und entsprechend für jedes einzelne Element des arrays die Methode aus meiner NumberUtil aufruft.

Habe das mit sehr großen arrays und tausenden von Durchläufen getestet, und ob nun die ArrayUtil und die NumberUtil oder die Argumente der Methoden final sind oder nicht, macht wie gesagt keinen Unterschied.

Und, ja, ich habe die Ausgabe der Methoden über die Konsole ausgegeben (damit nicht verwendete Ergebnisse nicht womöglich wegoptimiert werden. Und die Zeit für die Konsolenausgabe nicht mitgestoppt...

Edit: Vielleicht wird es aus opitmierungsperspektive erst wichtig, wenn die Klassen auch nicht-statische Methoden haben?!

Edit2: Und vielleicht beschäftige ich mich auch grad zuviel mit "premature optimization"
 
Zuletzt bearbeitet:

hdi

Top Contributor
@Marco Ja ok im Bereich der GUI-Programmierung zB mag das wohl stimmen. Ich meine wie oft tauscht man denn die Referenz auf einen Button x oder so aus.. Aber ich finde man sollte grundsätzlich auf final verzichten, und nur wenn's nötig ist dazuschreiben (und nicht andersrum). Ich finde ein final impliziert die bewusste Design-Entscheidung, dass sich der Wert zur Laufzeit nicht ändern darf bzw. wird. Das musst du erstmal rechtfertigen können, zB im Hinblick auf die Software-Logik (eben so Dinge wie id's, wo final ja eigentlich immer zu sehen ist). Aber wenn du's nicht kannst, dann solltest du es auch nicht final machen. Denn der Nachteil von "Per-Default" finals ist, dass du dir damit erstmal ohne handfestes Argument einschränkst. Warum dir die Möglichkeit nehmen, zur Laufzeit dynamisch zu sein, oder abzuleiten, overriden etc? Und wenn dir irgendwann mal kommt, du willst das doch nicht final machen, dann darfst du erstmal refactoren: Setter erstellen, nicht vergessen den Kontroll-Code der bisher direkt im Konstruktor steht da reinzuziehen, usw. Es reicht imho erstmal den Setter private zu halten. Denn wenn man in der eigenen Klasse rumwerkelt, dann sollte man eigentlich wissen, welcher Zustand erlaubt ist und welcher nicht.

@nossek:
Und vielleicht beschäftige ich mich auch grad zuviel mit "premature optimization"

Es gibt oder gab hier mal jmd mit einer ganz guten Signatur. Die lautete:

There are two rules for optimization:
1) Don't do it
2) (For experts only) Don't do it yet

Da ist was dran.. Für 99% aller Apps gilt eh immer 1), egal wie expert du bist. Denn es ist sch*** egal ob deine Suchanfrage, Filterung oder Whatever in 13ms abläuft oder in 9ms. Und das sind schon Werte für sehr komplexe Berechnungen.
 
Zuletzt bearbeitet:

Murray

Top Contributor
M.E. hilft final vor allem, Fehler zu vermeiden; Performance-Aspekte sind aber durchaus auch da (wenn auch nicht so stark, wie man das vielleicht erwarten würde). Methoden, die final sind, kann der Compiler "inlinen", also quasi an die Stelle des Aufrufs kopieren. Das spart etwas Zeit für den Methodenaufruf, vergrößert aber (bei nicht-trivialen Methoden) den (Byte-)Code.

Beispiel:
Java:
public class Final {

	private final int i1 = 1;
	private int i2 = 1;


	public final int getI1() {
		return i1;
	}

	public int getI2() {
		return i2;
	}

	public final int getI11() {
		return getI1();
	}

	public int getI22() {
		return getI2();
	}
}

Daraus entsteht folgender Bytecode:
Java:
Compiled from "Final.java"
public class Final extends java.lang.Object{
public Final();
  Code:
   0:	aload_0
   1:	invokespecial	#1; //Method java/lang/Object."<init>":()V
   4:	aload_0
   5:	iconst_1
   6:	putfield	#2; //Field i1:I
   9:	aload_0
   10:	iconst_1
   11:	putfield	#3; //Field i2:I
   14:	return

public final int getI1();
  Code:
   0:	iconst_1
   1:	ireturn

public int getI2();
  Code:
   0:	aload_0
   1:	getfield	#3; //Field i2:I
   4:	ireturn

public final int getI11();
  Code:
   0:	aload_0
   1:	invokevirtual	#4; //Method getI1:()I
   4:	ireturn

public int getI22();
  Code:
   0:	aload_0
   1:	invokevirtual	#5; //Method getI2:()I
   4:	ireturn

}

Man sieht, dass bei getI1() direkt der Wert der Konstanten in den Bytecode kopiert wurde; getI1() ist also geringfügig kürzer (und damit theoretisch zur Laufzeit auch schneller) als getI2(). Bei getI11() hat der Compiler den Vorteil allerdings nicht genutzt; hier bringt final bzgl. Performance nichts, da de rBytecode identisch ist mit der non-final-Variante getI22().
 

fastjack

Top Contributor
Kurzum: final verbessert Deine Performance nicht.

Vorsicht ist allerdings bei Murrays-Beispiel geboten, denn die Methoden getI1() und getI11() können nun auch nicht mehr vererbt werden!
 

Murray

Top Contributor
Kurzum: final verbessert Deine Performance nicht.
Das kann man m.E. so nicht sagen. Man sieht im (zugegebenermaßen konstruierten) Beispiel ja, das getI1() kürzer ist als getI2(). Wenn die VM eine Anweisung weniger abzuarbeiten hat, dann geht das geringfügig schneller. Bei dieser trivialen Methode ist sogar der Bytecode kürzer als in der non-final-Variante, wodurch Laden und Verifizieren der Klassen ebenfalls etwas beschleunigt werden sollten.
Aber: dieser Effekte sind sehr, sehr klein.

Vorsicht ist allerdings bei Murrays-Beispiel geboten, denn die Methoden getI1() und getI11() können nun auch nicht mehr vererbt werden!
Wie HDI schon sagte: vererbt sehr wohl, aber wer von dieser Klasse erbt, der kann die Implementierung dieser Methoden nicht mehr verändern, weil er sie nicht überschreiben kann. Das kann aber manchmal durchaus gewünscht sein.
 

hdi

Top Contributor
Also ich finde man sollte final nicht auf Grund von Performance einsetzen, so einfach. Soweit ich weiß fehlt es bisher weltweit an einem Exempel aus der Praxis, bei dem es im Hinblick auf Performance etwas gebracht hat Dinge final zu machen.
 

musiKk

Top Contributor
Say what? :autsch: Hast du denn keine sich ändernden Daten in deiner Software oder was? final kommt bei mir nur in sehr seltenen Fällen vor, zB bei Membern für eine id.

Falls Du Eclipse verwendest: Einfach mal die entsprechende Save Action aktivieren. Passiert mir recht oft, dass da zahlreiche finals hinzugefügt werden (sowohl bei eigenem als auch bei fremdem Code).

Soweit ich weiß fehlt es bisher weltweit

Ich kenne auch keinen aus Bielefeld...
 
B

...ButAlive

Gast
Naja final bringt schon etwas.

Zitat aus der VM Specifiaction:

... If a method is final or implicitly final, a compiler or a runtime code generator can safely "inline" the body of a final method, replacing an invocation of the method with the code in its body.

Das heißt wenn eine Methode final ist kann eine Methode leichter geinlined wird.

Java:
class A{
   public final void foo(){
        System.out.println("HALLO WELT");
   }
   
   public void bar(){
        foo();
    }
}

Kann problemlos umgewandelt werden in:

Java:
class AInline{

    public final void foo(){
        System.out.println("HALLO WELT");
    }
 
   public void bar(){
        System.out.println("HALLO WELT");
    }
}

Ohne final ginge das nicht, da es dann eine Klasse B geben könnte die die Methode foo überschreibt, und somit das Verhalten von bar ändert.

Durch final kann die JVM oder der Compiler den Code einfach inlinenen was günstiger ist als ein Methodenaufruf, da kein Methodenstack angelegt werden muss, keine Parameterreferencen kopiert werden müssen, und was sonst so zu einem Methodenaufruf gehört.

Im Großen und Ganzen ist das Microoptimierung. Final sollte trotzdem so oft wie möglich eingesetzt werden um das Open-Closed Prinzip und damit das Liskovsches Substitutionsprinzip einzuhalten.
 

hdi

Top Contributor
Jetzt fängt wieder einer an... Wir haben bereits geklärt dass final in der Theorie mehr Performance bringen kann, es aber aus diesem Grunde nicht in der Praxis eingesetzt werden sollte.

Im Großen und Ganzen ist das Microoptimierung.
Ganz genau. Und das bringt nur Ärger.

Final sollte trotzdem so oft wie möglich eingesetzt werden um das Open-Closed Prinzip und damit das Liskovsches Substitutionsprinzip einzuhalten.
Hast du den Artikel selbst überhaupt gelesen? Wenn du überall final hinklatscht dann ist da nix mehr mit Erweiterung. Keine Ableitung (final class), kein Override (final method), und mit "geschlossen für Modifikationen" ist nur Datenkapselung gemeint (Modifikation über Setter) und nicht, dass der Wert selbst sich niemals ändern darf.
 
B

...ButAlive

Gast
Klar hab ich den Artikel gelesen. Hast du meinen Beitrag gelesen?

Ich habe mir die Mühe gemacht in der Spezifikation nach einem Hinweis zu suchen wieso final Performazevorteile bringt. Das einzige was dazu drin steht, ist das inlinen von Code durch den Compiler/JIT, das war ein Askept der noch nicht aufgeführt war und da die Frage war wieso final Performanzvorteile bringt dachte ich, dass ich ihn schreiben kann. Falls nicht bitte ich dich um Entschuldigung.

Was final wahrlos hinklatschen angeht, stimme ich dir zu, beim Programmieren darf man ruhig nachdenken. Nur 99% der Bugs die ich so täglich fixe gehen entweder darauf zurück, das Klassen maximal mutabel sind oder Klassen Methoden wahrlos überschreiben und somit das Verhalten von anderen Methoden ändern. Beides wäre durch final nicht möglich.

und mit "geschlossen für Modifikationen" ist nur Datenkapselung gemeint (Modifikation über Setter) und nicht, dass der Wert selbst sich niemals ändern darf.

Das hast du irgendwie falsch verstanden. Mit "Closed for Modifikation" ist nicht der Zustand eines Objektes gemeint, sondern das Verhalten einer Klasse hinsichtlich Vererbung.
 

hdi

Top Contributor
das inlinen von Code durch den Compiler/JIT, das war ein Askept der noch nicht aufgeführt war
Schau dir mal den Beitrag von Murray weiter oben an ;) (STRG+F und "inline"). Aber unabhängig von diesem speziellen Hinweis (natürlich kann man mal ein Posting oder einen Satz überlesen bzw das topic nur überfliegen wenn man sich einhakt) gab es jetzt schon diverse Antworten in denen gesagt wurde:
1) final kann Performance bringen in der Theorie
2) in der Praxis sollte der TO das aber gleich wieder vergessen
Deswegen habe ich mich gefragt warum du die Performance-Geschichte jetzt wieder aufrollst.

Was final wahrlos hinklatschen angeht, stimme ich dir zu, beim Programmieren darf man ruhig nachdenken. Nur 99% der Bugs die ich so täglich fixe gehen entweder darauf zurück, das Klassen maximal mutabel sind oder Klassen Methoden wahrlos überschreiben und somit das Verhalten von anderen Methoden ändern. Beides wäre durch final nicht möglich.
Wie du schon sagst, man kann auch mal nachdenken. Wer "wahrlos" überschreibt der sollte den Job halt nicht machen. Ich finde man kann nicht sagen "Ich mach das final weil sonst jemand, der null Ahnung hat von dem was er da tut, einen Fehler machen könnte". Ich weiß ja nicht wo du arbeitest, aber wenn das 99% der Bugs sind, dann such dir andere Kollegen. Und "beides wäre durch final nicht möglich" - richtig. Schon mal überlegt, dass es vllt einen Grund gab dass die Methode overrided wurde? Da hat die Impementierung aus der Vaterklasse nicht ausgereicht. Ok, mach sie final, dann kann man keinen Fehler machen. weil man nämlich nichts machen kann, ist das jetzt besser?

edit: Und warum Murray sich bei dir bedankt dafür dass du das wiederholst was er gesagt hat versteh ich nicht, aber da hat wohl jmd was gegen mich ;(
 
Zuletzt bearbeitet:

Antoras

Top Contributor
Kleine Anmerkung von mir zu diesem Thema, auf die nicht eingegangen werden muss:

Um final wirklich zu verstehen muss man funktionale Programmierung verstanden haben.
 
B

...ButAlive

Gast
Sorry bei das Wörtchen inline hab ich in Murrays Posting anscheinend überlesen und mich mehr auf das Codebeispiel und den Bytecode konzentriert, da wird ja keine Methode geinlined und ich dachte es geht da um das laden der Konstante im Vergleich zu einer nicht Konstante.

99% ist vielleicht etwas übertrieben, aber es ist ein großer Teil. Die Bugs die ich so kenne entstehen oft dadurch, dass eine kleine Änderung große Auswirkungen haben. In großen komplexen Systemen ist das nun mal so, dass man unmöglich alle Auswirkungen einer Änderung überblicken kann. Besonders fieß zu finden sind Fehler die durch eine indirekte Codeänderung, wie z.B. Ableitungen, reingekommen sind. Wenn ich meinen Code schon so robust mache, dass keine Änderungen möglich sind, signalisiere ich meinen Kollegen "wenn du diese Methode überschreibst, kann etwas schlimmes passieren" oder "wenn dieser Wert sich ändert, fällt etwas an einer ganz anderen Stelle um". Ohne das er/sie alle Zusammenhänge analysieren muss, kann er/sie sich eine andere Lösung ausdenken oder zu mir kommen und zusammen schauen ob es nicht doch geht.

Die Hemmschwelle ein "final" wegzumachen ist doch sehr hoch. Oder es mit einem Zitat aus dem Jornalismus zu sagen "Einer muss sich immer anstrengen, entweder derjenige der ließt oder derjenige der schreibt".
 

Murray

Top Contributor
edit: Und warum Murray sich bei dir bedankt dafür dass du das wiederholst was er gesagt hat versteh ich nicht, aber da hat wohl jmd was gegen mich ;(
Also ich bestimmt nicht.

"Dankenswert" fand ich nicht so sehr die Wiederholung, sondern die Aussage
Nur 99% der Bugs die ich so täglich fixe gehen entweder darauf zurück, das Klassen maximal mutabel sind oder Klassen Methoden wahrlos überschreiben und somit das Verhalten von anderen Methoden ändern. Beides wäre durch final nicht möglich.
 
B

bygones

Gast
Aber ich finde man sollte grundsätzlich auf final verzichten, und nur wenn's nötig ist dazuschreiben (und nicht andersrum). Ich finde ein final impliziert die bewusste Design-Entscheidung, dass sich der Wert zur Laufzeit nicht ändern darf bzw. wird. Das musst du erstmal rechtfertigen können, zB im Hinblick auf die Software-Logik (eben so Dinge wie id's, wo final ja eigentlich immer zu sehen ist). Aber wenn du's nicht kannst, dann solltest du es auch nicht final machen. Denn der Nachteil von "Per-Default" finals ist, dass du dir damit erstmal ohne handfestes Argument einschränkst. Warum dir die Möglichkeit nehmen, zur Laufzeit dynamisch zu sein, oder abzuleiten, overriden etc?
ich seh das genau anders rum. Man sollte begruenden, warum einen variable nicht final sein soll. Einfach per se mal einen Mutator hinzufuegen, weil der bestimmt irgendwann mal gebraucht werden koennte ist falsch. Code sollte nicht aufgrund von moeglichen Geschehnissen enstehen, sondern weil es der Verwender verlangt.
Ist einem zum Entwicklungszeitpunkt unklar, ob eine Variable geaendert werden soll, so ist es sicherer final zu setzen, da man dies spaeter ohne Probleme wieder rueckgaengig machen kann. Andersrum ist das, sobald der Code in verwendung ist (moeglich noch API) schwer bis gar nicht moeglich.
Du erstellst hoffentlich auch nicht automatisch fuer jeder Variable gleich getter und setter ?

Alles in allem sollte man defensiv programmieren. So wenig wie moeglich nach aussen geben und sowenig wie moeglich mutable gestalten. Erst wenn der aktive Bedarf da ist.

Ergo, solange es niemand zwingt deine Variablen / Klassen nicht final zu halten, gehoert ein final da in.

Final bei methoden zeigt hervorragend, ob diese Methode ueberschrieben werden soll oder nicht. Es zeigt bei Klassen eindeutig welche fuer Vererbung frei sind und bei Variablen welche mutable sind. Wer Dynamik braucht kann diese spaeter immer noch einbauen
 

mvitz

Top Contributor
Erstmal stimme ich bygones zu 100% zu und zum zweiten kommt diese Aussage

"Final erhöht die Performance"

bestimmt auch daher, dass es bei vernünftigem Einsatz in einer Multithreading Umgebung eben stimmt. Wenn hier soviel wie möglich final ist, dann kann man nahezu auf Synchronisation verzichten und auch die Sichtbarkeit von Änderungen muss nicht zwischen verschiedenen Threads geflusht werden. Bei so simplen aufrufen, wie der TO hier dargestellt hat, wird man da mit Sicherheit keinen Performancegewinn sehen.
 

Kr0e

Gesperrter Benutzer
Ich denke schon, dass es stimmt, dass final Performance Vorteile bringt:

Die JVM nutzt Method-Inlining (C/C++ Programmierern sagt das vlt noch was) bei final, static und private MEthods, sofern KEINE lokalen Variablen darin enthalten sind und es keinen Rückgabetypen gibt.

Sprich damit werden die Sprunganweisungen minimiert. Ich habe das bei meiner Serialisierungslibarry germerkt. Gerade wenn es unheimlich viele verschachtelte kleine Funktionen gibt, macht das viel (ok, soviel nun auch wieder nicht) aus. Außerdem geschieht inlining auch nur bei -server Varianten (Ok, ist ja heute überall so). Bei mir viel das z.b. bei Umwandlungsfunktionen ins Gewicht: Also in etwa sowas:

Converter.intToArray(54, byteArray); // ist static und ist void

In dem Fall würde die Funktion an den Stellen wo es laut dem Compiler Sinn macht, inlining erfahren.

Ich das mal auf den unendlich vielen Oracle Seiten gelesen. Leider hab ich grad keine Zeit , das wieder rauszusuchen. Also glaubt es oder zweifelt es an ;)

Gruß,
Chris

AUßERDEM: Wie Marco schon geschrieben hat, ist final ein wichtiges Sprachmittel für Multithreading. WEnn man sich mal das JavaMemoryModell anschaut, dann wird das eindeutig klar: final Variablen müssen z.b. NICHT synchronisiert werden (was logisch ist) aber es geht noch weiter, denn final Variablen agieren in die eine Richtung ähnlich den volatile Variablen, denn die Sichtbarkeit wird garantiert auch beim ThreadContext Wechsel.... Mit final zu arbeiten macht sehr viel Sinn!
 

ThreadPool

Bekanntes Mitglied
[...]
final Variablen müssen z.b. NICHT synchronisiert werden (was logisch ist)

Das ist trifft nur bei primitiven Typen zu. Alles andere sind Referenzen. Es ist schön wenn man eine Referenz auf final setzt, man den Inhalt dieser Referenz aber beliebig ändern kann. D.h. final List<Integer> lst = new ArrayList<Integer>(); muss immernoch synchronisiert werden wenn man Schreib- und Lesevorgänge parallel auf der Liste ausführt.
 

Marco13

Top Contributor
Edit2: Und vielleicht beschäftige ich mich auch grad zuviel mit "premature optimization"

Wenn es wirklich um messbare Performancevorteile geht: Ja. Da werden 1000 final's nicht so viel bringen wie ein unbedachtes 'new ArrayList()' oder ein überflüssiges 'Collections.sort()'...

Aber die Frage, wann und ob 'final' geht ja darüber hinaus:


Aber ich finde man sollte grundsätzlich auf final verzichten, und nur wenn's nötig ist dazuschreiben (und nicht andersrum). Ich finde ein final impliziert die bewusste Design-Entscheidung, dass sich der Wert zur Laufzeit nicht ändern darf bzw. wird. Das musst du erstmal rechtfertigen können, zB im Hinblick auf die Software-Logik (eben so Dinge wie id's, wo final ja eigentlich immer zu sehen ist). Aber wenn du's nicht kannst, dann solltest du es auch nicht final machen. Denn der Nachteil von "Per-Default" finals ist, dass du dir damit erstmal ohne handfestes Argument einschränkst. Warum dir die Möglichkeit nehmen, zur Laufzeit dynamisch zu sein, oder abzuleiten, overriden etc? Und wenn dir irgendwann mal kommt, du willst das doch nicht final machen, dann darfst du erstmal refactoren: Setter erstellen, nicht vergessen den Kontroll-Code der bisher direkt im Konstruktor steht da reinzuziehen, usw.

Ich bemühe mich auch, nicht unreflektiert irgendwelche Empfehlungen anzunehmen und weiterzugeben. Aber in diesem Punkt leuchten mir die Vorteile des "Minimize Mutability" ein, das immerhin kein geringerer als Josh Bloch in "Effective Java" propagiert:
"Classes should be immutable unless there's a very good reason to make them mutable....If a class cannot be made immutable, limit its mutability as much as possible."
(zu den Gründen: Siehe das entsprechende Buch)

Teilweise ist bygones (und andere) schon darauf eingegangen, aber ... so wie du die Frage stellst, klingt es natürlich sehr suggestiv: "Warum dir die Möglichkeit nehmen, zur Laufzeit dynamisch zu sein...?" ;) Es geht ja nicht um "dynamisch sein", sondern nur darum, dass man sich ganz genau im Klaren ist (und am Code deutlich macht) welche Zustände und Änderungen man erlaubt und welche nicht. Darum eine Suggestivfrage in die andere Richtung: Wenn du eine Klasse mit 10 Fields erstellst - klickst du dann erstmal pauschal in Eclipse auf "Generate Setters and Getters" für alle Fields :autsch: Wohl auch nicht ;)
Overriding wird durch 'final fields' ja nicht beeinflußt, aber durch 'final methods' - und auch da ist es eigentlich gut, pauschal bei allen 'final' dazuzuschreiben, außer, wenn man sich GANZ sicher ist (und auch deutlich machen will!) dass JEDER diese Methode überschreiben darf. Es gibt nicht viele Methoden, für die das der Fall ist - und die meisten, bei denen das der Fall ist, sind sowieso "protected abstract"...
Der Zusammenhang dieses Punktes mit den Open-Closed-Principle wird ja weiter unten schon erwähnt.


Das kann man m.E. so nicht sagen. Man sieht im (zugegebenermaßen konstruierten) Beispiel ja, das getI1() kürzer ist als getI2(). Wenn die VM eine Anweisung weniger abzuarbeiten hat, dann geht das geringfügig schneller.

Ja, das ist schon fast "Zufall", wegen der iconst-Instruktion. Bei einem 'private final int i=5' würde es ja schon nichts mehr bringen ;)

Ansonsten... bezogen sich alle beiträge auf das, was ich schon im 1. und 2. geschrieben oder angedeutet hatte:
- 'final' bei Methoden kann einen Vorteil bringen. Als Grund wurde bisher genannt, dass sie durch das 'fina' geinlinet werden können. Es KÖNNTE auch Vorteile bringen, weil sie das "Poly" in dem Wort "Polymorphie" ggf. auf "Mono" reduzieren könnte (in bezug auf [JavaSpecialists 158] - Polymorphism Performance Mysteries Explained ) aber das müßte man noch genauer durchdenken.
- Allgemein dient 'final' aber nicht höherer Performance, sondern einer Einschränkung (unerwünschter!) Veränderbarkeit, sowohl auf Ebene der Objekte als auch der Klassen.
 

fastjack

Top Contributor
Also bei Methoden, Klassen und auch Membern mag das ja sinnvoll sein, aber warum braucht ihr final bei Methodenparametern? Ich sage es ehrlich, in den meisten Fällern brauche ich es nicht. Warum?
Wenn ich einen Parameter als final deklariere, damit ich ihn in meiner 10-100, 200 oder 300? zeiligen Methode nicht versehentlich doch verändern kann, habe ich etwas bei der der Methode falsch gemacht. Ganz einfach, sie ist zu lang!

Lösung: Kürzere Methoden, mehr Methoden, mehr Klassen und schon brauchts keine final Parameter mehr ;)

edit: Das mit der Optimierung im gezeigten Beispiel ist übrigens kein muß für ein Compiler oder Runtime-Optimierer, sondern kann implementiert werden oder auch nicht (dann hat man eben man Pech gehabt, wenn man sich drauf verlassen hat).

nochmal edit: Man kann sich mit der gezeigten Optimierung übrigens auch gut selber ins Knie schiessen. Klasse B wird dementsprechend inline optimiert und bekommt den Code von einer Methode von Klasse A eingeimpft. Super. Klasse A ändert sich, wird neu kompiliert, Klasse B nicht. Dumm gelaufen für Klasse B.
Ähnlich ist es mit dem berühmten "public final static String", dessen Wert auch schön direkt in den Bytecode anderer Klassen geht, während bei anderen atomare Datentypen ein Verweis darauf in den Bytecode geht.
 
Zuletzt bearbeitet:

musiKk

Top Contributor
Also bei Methoden, Klassen und auch Membern mag das ja sinnvoll sein, aber warum braucht ihr final bei Methodenparametern? Ich sage es ehrlich, in den meisten Fällern brauche ich es nicht. Warum?

Das würde mich auch interessieren. Es wird zwar immer wieder gepredigt, aber üblicherweise ohne Begründung. Ich verwende Parameter immer dann neu, wenn ich sie im Rahmen der Anfangsprüfung modifiziere (z. B. [c]String#trim()[/c] ausführen oder eine [c]null[/c]-Referenz durch einen Default-Wert ersetzen). Ich möchte mal sehen, wie das lesbarer werden soll, wenn man sich dafür neue Variablennamen aus dem Hintern ziehen muss.

Man kann sich mit der gezeigten Optimierung übrigens auch gut selber ins Knie schiessen. Klasse B wird dementsprechend inline optimiert und bekommt den Code von einer Methode von Klasse A eingeimpft. Super. Klasse A ändert sich, wird neu kompiliert, Klasse B nicht. Dumm gelaufen für Klasse B.

Ich war bisher davon ausgegangen, dass das Inlining in der JVM stattfindet und nicht im Compiler. Quellen dafür wären aber mal interessant.
 

Marco13

Top Contributor
Bei sowas wie [c]public static final int[/c] kann man dieses "Einsetzen" recht leicht testen, mit zwei Klassen, von denen man dann per Hand nur die Klasse mit dem int neu compiliert.
 

musiKk

Top Contributor
Bei Konstanten (primitive Datentypen, Strings und Klassen-Objekte) sollte es ja klar sein. Die werden per [c]ldc[/c] direkt aus dem Constant Pool geholt. Mir ging es eher um Inlining von Methoden.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
T KLasse das bessere Array Java Basics - Anfänger-Themen 16
M Bessere bzw. kürzere Variante für Code? Java Basics - Anfänger-Themen 2
cyro Best Practice Bessere Alterative zu ArrayList gesucht Java Basics - Anfänger-Themen 3
O Funktioniert dies? Und gibt es eine bessere Lösung? Java Basics - Anfänger-Themen 6
S Bessere Lösung? Java Basics - Anfänger-Themen 4
S Bessere Lösung zu häufigem instanceof Java Basics - Anfänger-Themen 25
F bräuchte eine bessere entwicklungsumgebung Java Basics - Anfänger-Themen 2
S unschöne schleifen.jemand ne bessere idee Java Basics - Anfänger-Themen 4
S LineNumberReader - bessere Lösung möglich? - Log4J Java Basics - Anfänger-Themen 9
J Wartezustand in Endlosschleife - bessere Alternativen Java Basics - Anfänger-Themen 20
G Bessere Lösung für SQL STMNT ? (Schneller?) Java Basics - Anfänger-Themen 4
G was ist die bessere Variante Java Basics - Anfänger-Themen 4
O HashTable kann ohne Performance-Verlust in Multithreaded-Anwendungen eingesetzt werden. Java Basics - Anfänger-Themen 6
N Java-Performance messen Java Basics - Anfänger-Themen 1
B Performance-Vergleich mit C++ Java Basics - Anfänger-Themen 55
P Priority Queue Performance Java Basics - Anfänger-Themen 3
P Performance Array und Liste Java Basics - Anfänger-Themen 13
S Performance von byte[], short[], int[]..? Java Basics - Anfänger-Themen 24
I Erste Schritte Resource Bundle - Alles in einem File oder mehrere? => Faktor Performance Java Basics - Anfänger-Themen 2
E Hilfe zur Performance Verbesserung gesucht Java Basics - Anfänger-Themen 1
G Performance - höhere Anzahl Swing Elemente Java Basics - Anfänger-Themen 5
S Performance-/Stress Test für Webanwendung Java Basics - Anfänger-Themen 2
R Datei kopieren: Performance erhöhen Java Basics - Anfänger-Themen 10
S Wie performance lastig sind rekursionen Java Basics - Anfänger-Themen 13
J Softwaresynthesizer Performance? Java Basics - Anfänger-Themen 11
I Anzahl einer Liste (Performance) Java Basics - Anfänger-Themen 2
J Performance Vergleich von if-Abfragen mit mehreren Bedingungen Java Basics - Anfänger-Themen 9
S Performance HashMap<=>Array Java Basics - Anfänger-Themen 17
J Arrays erweitern - Performance vs Speicherverbrauch Java Basics - Anfänger-Themen 6
M Einträge in Dateien zählen - Performance-Problem Java Basics - Anfänger-Themen 10
S unterschied in performance Java Basics - Anfänger-Themen 4
hdi Worst-Performance-Award für Arbeiten mit ListModel Java Basics - Anfänger-Themen 7
hdi Performance Frage (Threads,Swing) Java Basics - Anfänger-Themen 4
V Performance Lesen und Schreiben aus/in Streams Java Basics - Anfänger-Themen 4
C große Matrizen, Performance, (Pointer?) Java Basics - Anfänger-Themen 6
G import .; - Speicherauslastung, Performance Java Basics - Anfänger-Themen 14
G Performance Java Basics - Anfänger-Themen 18
C Performance IO vs. NIO Java Basics - Anfänger-Themen 5
S dynamic arrays/ performance Java Basics - Anfänger-Themen 2
RaoulDuke Arbeitsweise / Speichernutzung / Performance Java Basics - Anfänger-Themen 10
T Ich brauche eine Schleife die eine beliebige Zahl so lange durch 10 teilt bis zur Null Java Basics - Anfänger-Themen 5
X wie bekomme ich durch Eingabeaufforderung definierte double in einen Befehl, welcher 3 erwartete double braucht? Java Basics - Anfänger-Themen 3
T float soll durch schleife die größte mögliche Zahl herausfinden, Ausgabe ist aber "Infinity" Java Basics - Anfänger-Themen 1
H Counter durch gepresste Taste nur auf 1 erhöhen und nicht durchzählen lassen Java Basics - Anfänger-Themen 7
T Eingabe durch eine Zahl dividieren nachgucken? Java Basics - Anfänger-Themen 4
G Programm läuft durch, ohne Eingabe aus dem Chat abzuwarten Java Basics - Anfänger-Themen 4
S IntelliJ geht alle Klassen durch Java Basics - Anfänger-Themen 9
A 1 Leerzeichen durch zwei Leerzeichen ersetzen Java Basics - Anfänger-Themen 4
E Durch Muster in Array iterieren Java Basics - Anfänger-Themen 3
Thomas06 Wie kann man mithilfe von boolean herausfinden ob eine zahl durch 5 und 7 teilbart ist ? Java Basics - Anfänger-Themen 7
A JTextArea entfernen und durch neuen Text ersetzen Java Basics - Anfänger-Themen 8
B Den Dateipfad einer Java Datei durch Code in Selbiger finden? Java Basics - Anfänger-Themen 10
T Variable durch Action Listener ändern Java Basics - Anfänger-Themen 2
B Attribute eines Objekts einer Klasse durch statische Methode einer 2. Klasse ändern? Java Basics - Anfänger-Themen 32
Agent4nobody Programmstart durch aufruf des interpreters funktioniert nicht Java Basics - Anfänger-Themen 14
obiwanke Ziffern durch ASCII Character ersetzen Java Basics - Anfänger-Themen 8
J Speichern von zwei Variablen durch Auslesen aus einem Numberfield Java Basics - Anfänger-Themen 2
sserio Java Fx, wie erstellt man einen EventHandler, der durch das Drücken eines Button Texte in eine Table view einfügt Java Basics - Anfänger-Themen 17
S Durch HashMap iterieren Java Basics - Anfänger-Themen 8
A Wenn eine Zahl durch 7 teilbar ist, soll statt der Zahl ein ‘*‘ angezeigt werden. java? Java Basics - Anfänger-Themen 47
K mit <<1 kann man mal 2 machen, mit >>2 geteilt durch zwei und was bewirkt <<<1 und >>>1? Java Basics - Anfänger-Themen 5
A Verarbeiten einer Excel Datei durch das java-Programm Java Basics - Anfänger-Themen 3
C In String, Buchstaben ersetzen durch andere Buchstaben Java Basics - Anfänger-Themen 26
F Initialisieren eines Web-Mp3 Players in Tabs durch "booleans" erst wenn Tab geöffnet wird ...? Java Basics - Anfänger-Themen 1
W Werte durch Konsole einlesen Java Basics - Anfänger-Themen 10
C if-Konstrukt durch switch-Konstrukt ersetzen Java Basics - Anfänger-Themen 14
OZAN86 For Schleife von 1-50 die Zahlen werden durch ein Komma getrennt Java Basics - Anfänger-Themen 10
Bademeister007 Operatoren Alle Zahlen einer ArrayList die durch 5 teilbar ist Java Basics - Anfänger-Themen 2
Y Wie kann ich Konsoleneingaben durch den Scanner mit JUnit 4 testen? Java Basics - Anfänger-Themen 1
yoskaem Text Color durch Klicken eines Buttons in anderer Activity ändern Java Basics - Anfänger-Themen 2
N for Schleife durch Rekursion ersetzen Java Basics - Anfänger-Themen 6
N Probleme beim printen von Arrays durch for Schleife Java Basics - Anfänger-Themen 3
L Iterieren durch eine ArrayList. Integer Array wird übergeben Java Basics - Anfänger-Themen 17
J Eine Position im String durch einen Integer - Wert teilen Java Basics - Anfänger-Themen 5
F Methoden Bitte Helft mir meinen Fehler zu finden. Möchte in diesem Bankenprogramm durch die Konsoleneingabe auswählen welches Konto reduziert und welches erhö Java Basics - Anfänger-Themen 17
E 2D Array - char durch die Matrix "wandern" lassen Java Basics - Anfänger-Themen 7
E Objekt durch Benutzer über Konsole erzeugen - Java Java Basics - Anfänger-Themen 3
F Methode für Teilbarkeit durch 5 tut was anderes.... Java Basics - Anfänger-Themen 3
H Aufruf von Methoden durch Methoden Java Basics - Anfänger-Themen 3
H Wie kann ich durch Methoden definiren? Java Basics - Anfänger-Themen 8
O Mehrfache Scanner-Eingabe durch Komma getrennt Java Basics - Anfänger-Themen 6
M String array durch Eingabe begrenzen Java Basics - Anfänger-Themen 7
J Dynamisches Array durch split()-Funktion? Java Basics - Anfänger-Themen 3
O Typparameter durch Wildcards verallgemeinern Java Basics - Anfänger-Themen 3
G Benutzereingaben durch Zeilenumbruch trennen und in Array individueller Größe speichern Java Basics - Anfänger-Themen 20
B Import Tabelle - Struktur durch User einstellbar Java Basics - Anfänger-Themen 4
K Durch eine Text eingabe etwas Ausführen Java Basics - Anfänger-Themen 5
T Konsolenscanner startet nicht durch Aufruf von Actionlistener Java Basics - Anfänger-Themen 4
A OOP Variable in anderer Klasse durch Methode aufrufen und einer anderen Variable gleichsetzen Java Basics - Anfänger-Themen 2
F Ein Datum (int) durch Methode als String formatieren Java Basics - Anfänger-Themen 2
B OOP While Schleife läuft Endlos durch externen aufruf Java Basics - Anfänger-Themen 2
D While Schleife bei Bedarf durch Eingabe stoppen Java Basics - Anfänger-Themen 15
CptK Interface Curser durch Bild ersetzen & MouseListner Java Basics - Anfänger-Themen 2
H OOP eine Zahl immer weiter durch 2 teilen Java Basics - Anfänger-Themen 15
I Null-Überprüfung durch Lambda-Expressions abkürzen Java Basics - Anfänger-Themen 8
W Teilstring durch Teilstring mittels StringBuilder ersetzen Java Basics - Anfänger-Themen 7
N Denksportaufgabe durch Algorithmus lösen Java Basics - Anfänger-Themen 2
H Array mit Zahlen die durch 3 und 5 teilbar sind erstellen Java Basics - Anfänger-Themen 13
D Interface Frame doppelt durch Aufruf der GUI Klasse Java Basics - Anfänger-Themen 1
J Die Zahl herausfinden die durch 2 - 30 Teilbar ist... Java Basics - Anfänger-Themen 17

Ähnliche Java Themen

Neue Themen


Oben