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.