Wat is het nut van “laatste klas” in Java?

Ik ben een boek aan het lezen over Java en er staat dat je de hele klasse als finalkunt declareren. Ik kan niets bedenken waar ik dit zou gebruiken.

Ik ben net nieuw in programmeren en ik vraag me af of programmeurs dit daadwerkelijk gebruiken in hun programma’s. Als ze dat doen, wanneer gebruiken ze het dan zodat ik het beter kan begrijpen en weet wanneer ik het moet gebruiken.

Als Java objectgeoriënteerd is en u verklaart een klasse final, houdt dat dan niet op dat een klasse de kenmerken van objecten heeft?


Antwoord 1, autoriteit 100%

Allereerst raad ik dit artikel aan: Java: When om een laatste les te maken


Als ze dat doen, wanneer gebruiken ze het dan zodat ik het beter kan begrijpen en weet wanneer ik het moet gebruiken.

Een finalles is gewoon een les die niet kan worden verlengd.

(Het betekent niet dat alle verwijzingen naar objecten van de klasse zich zouden gedragen alsof ze als finalzijn gedeclareerd.)

Wanneer het nuttig is om een klas als definitief te verklaren, wordt behandeld in de antwoorden op deze vraag:

Als Java objectgeoriënteerd is en u verklaart een klasse final, houdt dit dan niet op dat een klasse de kenmerken van objecten heeft?

In zekere zin wel.

Door een klasse als definitief te markeren, schakelt u een krachtige en flexibele functie van de taal voor dat deel van de code uit. Sommige klassen zouden echter niet (en in bepaalde gevallen kunnenniet) ontworpen zijn om op een goede manier rekening te houden met subklassen. In deze gevallen is het logisch om de klasse als definitief te markeren, ook al beperkt het OOP. (Houd er echter rekening mee dat een laatste klas nog steeds een andere niet-finale klas kan verlengen.)


Antwoord 2, autoriteit 34%

In Java kunnen items met de finalmodifier niet worden gewijzigd!

Dit omvat eindklassen, eindvariabelen en eindmethoden:

  • Een laatste les kan niet worden verlengd met een andere les
  • Aan een laatste variabele kan geen andere waarde worden toegewezen
  • Een definitieve methode kan niet worden overschreven

Antwoord 3, autoriteit 6%

Een scenario waarbij final belangrijk is, wanneer u om veiligheidsredenen overerving van een klasse wilt voorkomen. Zo kun je ervoor zorgen dat de code die je gebruikt niet kan worden overschrevendoor iemand.

Een ander scenario is voor optimalisatie: ik meen me te herinneren dat de Java-compiler enkele functieaanroepen van eindklassen inline heeft. Dus, als je a.x()aanroept en a wordt verklaard tot final, weten we tijdens het compileren wat de code zal zijn en kunnen we inline in de aanroepende functie. Ik heb geen idee of dit ook daadwerkelijk wordt gedaan, maar met definitief is het een mogelijkheid.


Antwoord 4, autoriteit 5%

Het beste voorbeeld is

openbare laatste les String

wat een onveranderlijke klasse is en niet kan worden uitgebreid.
Natuurlijk komt er meer bij kijken dan alleen de klas definitief maken om onveranderlijk te zijn.


Antwoord 5, autoriteit 3%

Als je je de klassenhiërarchie voorstelt als een boom (zoals het is in Java), kunnen abstracte klassen alleen vertakkingen zijn en laatste klassen zijn klassen die alleen bladeren kunnen zijn. Klassen die in geen van beide categorieën vallen, kunnen zowel takken als bladeren zijn.

Er is hier geen sprake van schending van OO-principes, de finale zorgt gewoon voor een mooie symmetrie.

In de praktijk wil je final gebruiken als je wilt dat je objecten onveranderlijk zijn of als je een API schrijft, om de gebruikers van de API te laten weten dat de klasse gewoon niet bedoeld is voor uitbreiding.


Antwoord 6, autoriteit 3%

Relevante literatuur: Het open-gesloten principedoor Bob Martin.

Belangrijkste citaat:

Software-entiteiten (klassen, modules,
Functies, enz.) moeten openstaan voor:
Verlenging, maar gesloten voor
Wijziging.

Het finalsleutelwoord is het middel om dit in Java af te dwingen, of het nu wordt gebruikt voor methoden of voor klassen.


Antwoord 7, autoriteit 2%

Het trefwoord finalzelf betekent dat iets definitief is en op geen enkele manier mag worden gewijzigd. Als een klasse als finalgemarkeerd is, kan deze niet worden uitgebreid of gesubklasseerd. Maar de vraag is waarom markeren we een klas final? IMO zijn er verschillende redenen:

  1. Standaardisatie:sommige klassen voeren standaardfuncties uit en zijn niet bedoeld om te worden gewijzigd, b.v. klassen die verschillende functies uitvoeren met betrekking tot stringmanipulaties of wiskundige functies enz.
  2. Veiligheidsredenen: soms schrijven we klassen die verschillende authenticatie- en wachtwoordgerelateerde functies uitvoeren en we willen niet dat ze door iemand anders worden gewijzigd.

Ik heb gehoord dat Markeerklasse finalVerbetert de efficiëntie, maar eerlijk gezegd kon ik dit argument niet vinden om veel gewicht te dragen.

Als Java object georiënteerd is, en u een klassenfinale declareert, het niet
Stop het idee van de klas met de kenmerken van objecten?

Misschien ja, maar soms is dat het beoogde doel. Soms doen we dat om grotere veiligheidsvoordelen te bereiken enz. Door het vermogen van deze klasse te offeren die moet worden uitgebreid. Maar een laatste klasse kan nog steeds één klasse verlengen als het nodig heeft.

Aan een kant opmerking moeten we de voorkeur geven aan samenstelling over erfenis en finalTrefwoord helpt eigenlijk om dit principe te handhaven.


8, Autoriteit 2%

final classKan voorkomen dat u de publieke API hebt gebroken wanneer u nieuwe methoden

toevoegt

Stel dat op versie 1 van uw BaseCLASSE U doet:

public class Base {}

en een klant doet:

class Derived extends Base {
    public int method() { return 1; }
}

Als u vervolgens in versie 2 wilt toevoegen, wilt u een method-methode toevoegen aan Base:

class Base {
    public String method() { return null; }
}

het zou de clientcode breken.

Als we hadden gebruikt final class BaseIn plaats daarvan zou de klant niet in staat zijn geweest om te erven, en de methode-toevoeging zou de API niet breken.


9

Een laatste les is een les die niet kan worden verlengd. Methoden kunnen ook als definitief worden gedeclareerd om aan te geven dat ze niet door subklassen kunnen worden overschreven.

Voorkomen dat de klasse wordt gesubklasseerd, kan met name handig zijn als u API’s of bibliotheken schrijft en wilt voorkomen dat deze wordt uitgebreid om het basisgedrag te wijzigen.


Antwoord 10

Wees voorzichtig als je een les ‘final’ maakt. Omdat als je een eenheidstest voor een laatste klasse wilt schrijven, je deze laatste klasse niet kunt subclasseren om de afhankelijkheidsbrekende techniek “Subclass and Override Method” te gebruiken die wordt beschreven in Michael C. Feathers’ boek “Working Effectively with Legacy Code” . In dit boek zei Feathers: “Serieus, het is gemakkelijk te geloven dat verzegeld en definitief een verkeerde vergissing zijn, dat ze nooit aan programmeertalen hadden mogen worden toegevoegd. Maar de echte fout ligt bij ons. Als we rechtstreeks afhankelijk zijn van bibliotheken die buiten onze controle liggen, we vragen gewoon om problemen.”


Antwoord 11

In Java gebruikt laatste zoekwoord voor onderstaande gelegenheden.

  1. Laatste variabelen
  2. Definitieve methoden
  3. Laatste lessen

In Java kunnen definitieve variabelen niet opnieuw worden toegewezen, final classeskunnen niet worden uitgebreid en definitieve methoden kunnen niet worden overschreven.


Antwoord 12

Als de klas is gemarkeerd als final, betekent dit dat de structuur van de klas door niets van buitenaf kan worden gewijzigd. Waar dit het meest zichtbaar is, is wanneer je traditionele polymorfe overerving doet, in principe zal class B extends Agewoon niet werken. Het is in feite een manier om sommige delen van uw code (to extent)te beschermen.

Ter verduidelijking: het markeren van klasse finalmarkeert de velden niet als finalen beschermt als zodanig niet de objecteigenschappen, maar in plaats daarvan de feitelijke klassenstructuur.

p>


Antwoord 13

OM HET LAATSTE KLASSEPROBLEEM AAN TE PAKKEN:

Er zijn twee manieren om een klas definitief te maken. De eerste is om het sleutelwoord final te gebruiken in de klassedeclaratie:

public final class SomeClass {
  //  . . . Class contents
}

De tweede manier om een klasse definitief te maken, is door alle constructors als privé te verklaren:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

Als u het als definitief markeert, bespaart u de moeite als u erachter komt dat het een definitief is, om te demonstreren naar deze testklasse. ziet er op het eerste gezicht openbaar uit.

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

Helaas, aangezien de enige constructor van de klasse privé is, is het onmogelijk om deze klasse uit te breiden. In het geval van de testklasse is er geen reden dat de klasse definitief zou zijn. De testklasse is een goed voorbeeld van hoe impliciete eindklassen problemen kunnen veroorzaken.

Dus je moet het als definitief markeren als je impliciet een klasse definitief maakt door de constructor privé te maken.


Antwoord 14

Een voordeel van het houden van een les als definitief:-

String-klasse wordt definitief gehouden, zodat niemand de methoden kan overschrijven en de functionaliteit kan wijzigen. niemand kan bijvoorbeeld de functionaliteit van de methode length() wijzigen. Het geeft altijd de lengte van een string terug.

De ontwikkelaar van deze klasse wilde dat niemand de functionaliteit van deze klasse zou veranderen, dus hield hij het als definitief.


Antwoord 15

Ja, soms wil je dit misschien, om veiligheids- of snelheidsredenen. Het is ook gedaan in C++. Het is misschien niet datvan toepassing op programma’s, maar meer nog voor frameworks.
http://www.glenmccl.com/perfj_025.htm


Antwoord 16

Definitieve lessen kunnen niet worden verlengd. Dus als je wilt dat een klasse zich op een bepaalde manier gedraagt en niemand de methoden overschrijft (met mogelijk minder efficiënte en meer kwaadaardige code), kun je de hele klasse declareren als definitieve of specifieke methoden die je niet wilt zijn veranderd.

Aangezien het declareren van een klasse niet verhindert dat een klasse wordt geïnstantieerd, betekent dit niet dat de klasse de kenmerken van een object niet meer heeft. Het is alleen dat je je aan de methoden moet houden zoals ze in de klasse zijn gedeclareerd.


Antwoord 17

beschouw FINAL als het “einde van de lijn” – die man kan geen nakomelingen meer produceren. Dus als je het op deze manier ziet, zijn er talloze scenario’s uit de echte wereld die je tegenkomt waarbij je een ‘einde van de regel’-markering voor de klas moet markeren. Het is Domain Driven Design – als uw domein eist dat een bepaalde ENTITY (klasse) geen subklassen kan maken, markeer het dan als DEFINITIEF.

Ik moet er rekening mee houden dat niets je ervan weerhoudt om een klasse “moet worden getagd als definitief” te erven. Maar dat wordt over het algemeen geclassificeerd als “misbruik van overerving”, en gedaan omdat je meestal een functie van de basisklasse in je klas wilt erven.

De beste aanpak is om naar het domein te kijken en het je ontwerpbeslissingen te laten bepalen.


Antwoord 18

Zoals hierboven gezegd, als je wilt dat niemand de functionaliteit van de methode kan veranderen, kun je deze als definitief verklaren.

Voorbeeld: bestandspad van toepassingsserver voor downloaden/uploaden, string splitsen op basis van offset, dergelijke methoden kunt u definitief verklaren, zodat deze methodefuncties niet worden gewijzigd. En als u dergelijke definitieve methoden in een aparte klasse wilt, definieer die klasse dan als Final-klasse. De Final-klasse heeft dus alle definitieve methoden, terwijl de als Final-methode kan worden gedeclareerd en gedefinieerd in de niet-finale klasse.


19

Definitieve klasse kan niet verder worden uitgebreid. Als we geen klasse in Java hoeven te maken, kunnen we deze aanpak gebruiken.

Als we alleen maar specifieke methoden moeten maken in een klasse om niet te worden overschreven, kunnen we gewoon het laatste zoekwoord voor hen plaatsen. Daar is de klas nog steeds erfenissen.


20

Android looper klasse is een goed praktisch voorbeeld hiervan.
http://developer.android.com/reference/android/os/looper.html

De Looper-klasse biedt bepaalde functionaliteit die niet bedoeld is om door een andere klasse te worden overschreven. Vandaar geen subklasse hier.


21

De andere antwoorden hebben zich gericht op wat final classvertelt de compiler: laat geen andere klasse toe om het te verklaren extendsverlengt en waarom dat wenselijk is.

Maar de compiler is niet de enige lezer van de uitdrukking final class. Elke programmeur die de broncode leest, leest dat ook. Het kan een snelheidsverbegrip helpen.

In het algemeen geldt dat als een programmeur Thing thing = that.someMethod(...);ziet en de programmeur het daaropvolgende gedrag wil begrijpen van het object dat toegankelijk is via het Thingobject-referentie, moet de programmeur rekening houden met de klassehiërarchie Thing: mogelijk veel typen, verspreid over veel pakketten. Maar als de programmeur final class Thingkent of leest, weten ze meteen dat ze niet zoveel Java-bestanden hoeven te zoeken en bestuderen, omdat er geen afgeleide klassen zijn: ze hoeven alleen Thing.javaen misschien zijn het de basisklassen.


Antwoord 22

Ik ken maar één echt gebruiksscenario: gegenereerde klassen

Onder de use-cases van gegenereerde klassen, ken ik er een: dependency inject b.v. https://github.com/google/dagger


Antwoord 23

Objectoriëntatie gaat niet over overerving, het gaat over inkapseling. En overerving verbreekt inkapseling.

Het is in veel gevallen volkomen logisch om een klassefinale uit te roepen. Elk object dat een “waarde” vertegenwoordigt, zoals een kleur of een geldbedrag, kan definitief zijn. Ze staan op zichzelf.

Als je bibliotheken schrijft, maak je klassen dan definitief, tenzij je ze expliciet laat inspringen om afgeleid te worden. Anders kunnen mensen uw klassen afleiden en methoden overschrijven, waardoor uw aannames / invarianten worden verbroken. Dit kan ook beveiligingsimplicaties hebben.

Joshua Bloch in “Effective Java” beveelt aan om expliciet te ontwerpen voor overerving of het te verbieden en hij merkt op dat ontwerpen voor overerving niet zo eenvoudig is.

Other episodes