it-swarm-eu.dev

Měl bych v jazyce Java používat „final“ pro parametry a místní obyvatele, i když nemusím?

Java umožňuje označovat proměnné (pole/místní/parametry) jako final, aby se zabránilo jejich opětovnému přiřazení. S poli je to velmi užitečné, protože mi pomáhá rychle zjistit, zda mají být některé atributy - nebo celá třída - neměnné.

Na druhé straně je pro místní obyvatele a parametry mnohem méně užitečné a obvykle se jim vyhýbám označení jako final, i když k nim nikdy nebude přiřazeno (se zjevnou výjimkou, když je třeba používá se ve vnitřní třídě). V poslední době jsem však narazil na kód, který používal finální, kdykoli to bylo možné, což podle mě technicky poskytuje více informací.

Už si nevěřím ve svůj programovací styl, zajímalo by mě, jaké jsou další výhody a nevýhody aplikace final kdekoli, jaký je nejběžnější průmyslový styl a proč.

114
Oak

Používám final stejným způsobem jako vy. Pro mě to vypadá zbytečně na lokálních proměnných a parametrech metody a neposkytuje užitečné užitečné informace.

Jedna důležitá věc je, že se snaží držujte mé metody krátké a čisté, každý dělá jeden úkol. Moje lokální proměnné a parametry tedy mají velmi omezený rozsah a používají se pouze pro jeden účel. Tím se minimalizuje šance na neúmyslné přiřazení.

Navíc, jak jistě víte, final nezaručuje, že nemůžete změnit hodnotu/stav (neprimitivní) proměnné. Pouze to, že po inicializaci nelze k tomuto objektu přiřadit odkaz . Jinými slovy, funguje hladce pouze s proměnnými primitivních nebo neměnných typů. Zvážit

final String s = "forever";
final int i = 1;
final Map<String, Integer> m = new HashMap<String, Integer>();

s = "never"; // compilation error!
i++; // compilation error!
m.put(s, i); // fine

To znamená, že v mnoha případech stále ještě neumožňuje pochopit, co se děje uvnitř kódu, a nepochopení může ve skutečnosti způsobit jemné chyby, které je těžké odhalit.

68
Péter Török

Váš Java styl programování a myšlenky jsou v pořádku - nemusíte tam pochybovat).

Na druhé straně to považuji za mnohem méně užitečné u místních obyvatel a parametrů a obvykle se jim vyhýbám označování jako konečné, i když k nim nikdy nebude přiřazeno (se zjevnou výjimkou, když je třeba použít ve vnitřní třídě) ).

Právě proto byste měli použít klíčové slovo final. Říkáte, že VY víte, že to nikdy nebude znovu přiděleno, ale nikdo jiný to neví. Použití final okamžitě znepříjemní váš kód, který je o něco více.

66
J.K.

Jednou z výhod použití final/const je to možné, že to snižuje mentální zatížení čtenáře vašeho kódu.

Můžete si být jisti, že hodnota/reference se nikdy později nezmění. Aby pochopil výpočet, nemusí věnovat pozornost úpravám.

Po tom, co jsem se naučil čistě funkční programovací jazyky, jsem si to změnil. Chlapče, to je úleva, pokud věříš „proměnné“, aby si vždy udržel svou počáteční hodnotu.

32
LennyProgrammers

final v parametrech metody a lokálních proměnných považuji za šum kódu. Java Java mohou být poměrně dlouhé (zejména u generik) - není třeba je dále vyrábět.

Pokud jsou testy jednotek zapsány správně, bude přiřazeno parametrům, které jsou „škodlivé“, takže by to nikdy nemělo být problémem. Vizuální srozumitelnost je důležitější než vyhýbání se možné chybě, která není vyzvednuta, protože vaše testy jednotek nemají dostatečné pokrytí.

Nástroje jako FindBugs a CheckStyle, které lze nakonfigurovat tak, aby přerušily sestavení, pokud je přiřazeno parametrům nebo místním proměnným, pokud vám tyto věci hluboce záleží.

Samozřejmě, pokud je potřebujete , aby byly konečné, například proto, že používáte hodnotu v anonymní třídě, pak žádný problém - to je nejjednodušší nejčistší řešení.

Kromě zjevného efektu přidání dalších klíčových slov do vašich parametrů, a tím je IMHO maskuje, může přidání konečných parametrů metody často způsobit, že kód v těle metody bude méně čitelný, což kód zhoršuje - být „dobrý“, kód musí být co nejčitelnější a nejjednodušší. Pro vymyslený příklad řekněme, že mám metodu, která musí pracovat případ necitlivě.

Bez final:

public void doSomething(String input) {
    input = input.toLowerCase();
    // do a few things with input
}

Jednoduchý. Čistý. Každý ví, co se děje.

Nyní s „finální“, možnost 1:

public void doSomething(final String input) {
    final String lowercaseInput = input.toLowerCase();
    // do a few things with lowercaseInput
}

Zatímco parametry final zastaví kódování přidávání kódu dále dolů od myšlení, že pracuje s původní hodnotou, existuje stejné riziko, že kód dále dolů může použít input místo lowercaseInput , což by nemělo a proti kterému nelze chránit, protože jej nemůžete vyjmout z rozsahu (nebo dokonce přiřadit null k input, pokud by to vůbec pomohlo).

S 'final', možnost 2:

public void doSomething(final String input) {
    // do a few things with input.toLowerCase()
}

Nyní jsme vytvořili ještě více šumu kódu a představili jsme hit výkonu, který jsme museli vyvolat toLowerCase() n krát.

S „finální“ možnost 3:

public void doSomething(final String input) {
    doSomethingPrivate(input.toLowerCase());
}

/** @throws IllegalArgumentException if input not all lower case */
private void doSomethingPrivate(final String input) {
    if (!input.equals(input.toLowerCase())) {
        throw new IllegalArgumentException("input not lowercase");
    }
    // do a few things with input
}

Mluvte o šumu kódu. Toto je vrak vlaku. Máme novou metodu, požadovaný blok výjimek, protože jiný kód ji může vyvolat nesprávně. Více jednotkových testů na pokrytí výjimky. Vše proto, abychom se vyhnuli jedné jednoduché a IMHO preferované a neškodné linii.

Existuje také problém, že metody by neměly být tak dlouhé, že je nelze snadno vizuálně zapojit a na první pohled vědět, že došlo k přiřazení parametru.

Myslím, že je dobrým zvykem/stylem, že pokud přiřadíte parametr, uděláte to každé brzy v metodě, nejlépe první řádek nebo přímo po základní kontrole vstupu, efektivně nahrazení pro metodu celá , která má v rámci metody konzistentní účinek. Čtenáři vědí, že jakékoli přiřazení bude zřejmé (v blízkosti podpisového prohlášení) a na konzistentním místě, což výrazně zmírňuje problém, kterému se přidávání finále snaží vyhnout. Vlastně jen zřídka přiřadím parametrům, ale pokud ano, vždy to udělám v horní části metody.


Všimněte si také, že final vás ve skutečnosti nechrání, jako by se na první pohled mohlo zdát:

public void foo(final Date date) {
    date.setTime(0); 
    // code that uses date
}

final vás úplně nechrání, pokud není typ parametru primitivní nebo neměnný.

22
Bohemian

Nechal jsem Eclipse dát final před každou lokální proměnnou, protože to považuji za to, aby byl program snáze čitelný. Nedělám to s parametry, protože chci udržovat seznam parametrů co nejkratší, v ideálním případě by měl zapadat do jednoho řádku.

7
maaartinus