Vitajte v novom Vyzyvatelia Java blog! Tento blog je venovaný náročným konceptom v programovaní v Jave. Osvojte si ich a budete na dobrej ceste stať sa vysoko kvalifikovaným programátorom Java.
Postup v tomto blogu si vyžaduje určité úsilie, aby ste ich zvládli, ale výrazne zlepšia vaše každodenné skúsenosti s vývojom v prostredí Java. Vyhýbanie sa chybám je jednoduchšie, keď viete, ako správne aplikovať základné programovacie techniky Java, a sledovanie chýb je oveľa jednoduchšie, keď viete presne, čo sa deje s vašim kódom Java.
Ste pripravení začať ovládať základné koncepty programovania v jazyku Java? Potom začnime s naším prvým Java Challengerom!
Terminológia: Preťaženie metódy
Kvôli termínu preťaženie, vývojári si myslia, že táto technika preťaží systém, ale to nie je pravda. V programovaní preťaženie metódy znamená použitie rovnakého názvu metódy s rôznymi parametrami.
Čo je to preťaženie metódy?
Metóda preťaženia je programovacia technika, ktorá umožňuje vývojárom používať rovnaký názov metódy viackrát v tej istej triede, ale s rôznymi parametrami. V takom prípade hovoríme, že metóda je preťažená. Výpis 1 zobrazuje jednu metódu, ktorej parametre sa líšia počtom, typom a poradím.
Zoznam 1. Tri typy preťaženia metód
Počet parametrov: verejná trieda Calculator {void spočítat (int číslo1, int číslo2) {} void spočítat (int číslo1, int číslo2, int číslo3) {}} Typ parametrov: verejná trieda Calculator {void vypočítať (int číslo1, int číslo2) ) {} výpočet neplatnosti (dvojité číslo1, dvojité číslo2) {}} Poradie parametrov: verejná trieda Calculator {výpočet prázdnoty (dvojité číslo1, int číslo2) {} výpočet neplatnosti (int číslo1, dvojité číslo2) {}}
Metóda preťaženia a primitívne typy
V zozname 1 vidíte primitívne typy int
a dvojitý
. S týmito a ďalšími typmi budeme viac pracovať, preto si nájdite chvíľu a prečítajte si primitívne typy v Jave.
Tabuľka 1. Primitívne typy v Jave
Typ | Rozsah | Predvolené | Veľkosť | Ukážkové literály |
boolean | pravda alebo lož | nepravdivé | 1 bit | pravda lož |
bajt | -128 .. 127 | 0 | 8 bitov | 1, -90, 128 |
char | Znak Unicode alebo 0 až 65 536 | \ u0000 | 16 bitov | 'a', '\ u0031', '\ 201', '\ n', 4 |
krátky | -32,768 .. 32,767 | 0 | 16 bitov | 1, 3, 720, 22,000 |
int | -2,147,483,648 .. 2,147,483,647 | 0 | 32 bitov | -2, -1, 0, 1, 9 |
dlho | -9 223 372 036 854 775 808 až 9 223 372 036 854 775 807 | 0 | 64 bitov | -4000L, -900L, 10L, 700L |
plavák | 3,40282347 x 1038, 1,40239846 x 10-45 | 0.0 | 32 bitov | 1,67e200f, -1,57e-207f, 0,9f, 10,4F |
dvojitý | 1,7976931348623157 x 10308, 4,9406564584124654 x 10-324 | 0.0 | 64 bitov | 1.e700d, -123457e, 37e1d |
Prečo by som mal používať preťaženie metód?
Preťaženie robí váš kód čistejším a ľahšie čitateľným a môže vám tiež pomôcť vyhnúť sa chybám vo vašich programoch.
Na rozdiel od výpisu 1 si predstavte program, kde ste mali viac vypočítať ()
metódy s názvami ako vypočítať
1, vypočítať2
, vypočítať3
. . . nie dobré, nie? Preťaženie vypočítať ()
metóda vám umožňuje používať rovnaký názov metódy a meniť iba to, čo je potrebné zmeniť: parametre. Je tiež veľmi ľahké nájsť preťažené metódy, pretože sú vo vašom kóde zoskupené.
Čo preťaženie nie je
Uvedomte si, že zmena názvu premennej nie je preťaženie. Nasledujúci kód sa nebude kompilovať:
public class Calculator {void spočítať (int firstNumber, int secondNumber) {} void spočítať (int secondNumber, int thirdNumber) {}}
Metódu tiež nemôžete preťažiť zmenou návratového typu v podpise metódy. Nasledujúci kód sa nebude kompilovať:
public class Calculator {dvojitý výpočet (int číslo1, int číslo2) {návrat 0,0;} dlhý výpočet (int číslo1, int číslo2) {návrat 0;}}
Preťaženie konštruktéra
Môžete preťažiť konštruktor rovnakým spôsobom, ako by ste použili metódu:
public class Calculator {private int number1; súkromné int číslo 2; verejná kalkulačka (int číslo1) {this.number1 = číslo1;} verejná kalkulačka (int číslo1, int číslo2) {this.number1 = číslo1; this.number2 = number2; }}
Prijmite výzvu preťaženia metódy!
Ste pripravení na svoj prvý Java Challenger? Poďme zistiť!
Začnite dôkladnou kontrolou nasledujúceho kódu.
Zoznam 2. Výzva na preťaženie pokročilej metódy
verejná trieda AdvancedOverloadingChallenge3 {statický reťazec x = ""; public static void main (String ... doYourBest) {executeAction (1); executeAction (1.0); executeAction (Double.valueOf ("5")); executeAction (1L); System.out.println (x); } static void executeAction (int ... var) {x + = "a"; } static void executeAction (Celé číslo var) {x + = "b"; } static void executeAction (Object var) {x + = "c"; } static void executeAction (krátke var) {x + = "d"; } static void executeAction (float var) {x + = "e"; } static void executeAction (dvojitá var) {x + = "f"; }}
Dobre, skontrolovali ste kód. Aký je výstup?
- befe
- bfce
- efce
- aecf
Skontrolujte svoju odpoveď tu.
Čo sa práve stalo? Ako JVM zostavuje preťažené metódy
Aby ste pochopili, čo sa stalo v zozname 2, potrebujete vedieť niečo o tom, ako JVM kompiluje preťažené metódy.
V prvom rade je to JVM inteligentne lenivý: na vykonanie metódy bude vždy vynaložené najmenšie možné úsilie. Keď teda uvažujete o tom, ako JVM zvláda preťaženie, nezabudnite na tri dôležité techniky kompilátora:
- Rozšírenie
- Box (autoboxing a unboxing)
- Varargs
Ak ste sa s týmito tromi technikami nikdy nestretli, malo by vám ich objasniť niekoľko príkladov. Upozorňujeme, že JVM ich vykonáva v uvedenom poradí.
Tu je príklad rozširovanie:
int primitiveIntNumber = 5; double primitiveDoubleNumber = primitiveIntNumber;
Toto je poradie primitívnych typov, keď sú rozšírené:
Rafael del NeroTu je príklad autoboxing:
int primitiveIntNumber = 7; Celé číslo wrapperIntegerNumber = primitiveIntNumber;
Všimnite si, čo sa deje v zákulisí, keď sa kompiluje tento kód:
Integer wrapperIntegerNumber = Integer.valueOf (primitiveIntNumber);
A tu je príkladrozbaľovanie:
Celé číslo wrapperIntegerNumber = 7; int primitiveIntNumber = wrapperIntegerNumber;
Pri kompilácii tohto kódu sa deje v zákulisí:
int primitiveIntNumber = wrapperIntegerNumber.intValue ();
A tu je príklad varargs; poznač si to varargs
je vždy posledný, ktorý sa má vykonať:
vykonať (int ... čísla) {}
Čo je to varargs?
Používa sa na variabilné argumenty, varargs
je v podstate pole hodnôt špecifikovaných tromi bodkami (...) Môžeme prejsť akokoľvek veľa int
čísla, ktoré chceme k tejto metóde.
Napríklad:
poprava (1,3,4,6,7,8,8,6,4,6,88 ...); // Mohli by sme pokračovať ...
Varargs je veľmi praktický, pretože hodnoty je možné odovzdať priamo metóde. Ak by sme používali polia, museli by sme vytvoriť inštanciu poľa s hodnotami.
Rozšírenie: Praktický príklad
Keď odovzdáme číslo 1 priamo k executeAction
metódou sa s ním JVM zaobchádza automaticky ako s int
. Preto číslo nejde do čísla executeAction (krátka var)
metóda.
Podobne, ak prekonáme číslo 1,0, JVM automaticky rozpozná toto číslo ako a dvojitý
.
Číslo 1.0 by samozrejme mohlo byť aj a plavák
, ale typ je vopred definovaný. Preto executeAction (dvojitá var)
metóda je vyvolaná v zozname 2.
Keď použijeme Dvojitý
typu obalu, existujú dve možnosti: buď číslo obalu možno rozbaliť na primitívny typ, alebo ho možno rozšíriť na Objekt
. (Pamätajte, že každá trieda v jazyku Java rozširuje Objekt
triedy.) V takom prípade sa JVM rozhodne obkľúčiť Dvojitý
typ do Objekt
pretože to vyžaduje menej úsilia, ako by to vyžadovalo rozbalenie, ako som už vysvetlil.
Posledné číslo, ktoré minieme, je 1L, a pretože sme tentokrát špecifikovali typ premennej, je to tak dlho
.
Video výzva! Preťaženie metódy ladenia
Ladenie je jedným z najjednoduchších spôsobov, ako úplne absorbovať programovacie koncepty a zároveň vylepšiť váš kód. V tomto videu môžete sledovať, kým ladím a vysvetľujem výzvu preťaženia metódy:
Časté chyby s preťažením
Teraz ste už pravdepodobne prišli na to, že pri preťažení metódami to môže byť zložité, takže si zvážme niekoľko výziev, s ktorými sa pravdepodobne stretnete.
Autoboxovanie s obalmi
Java je programovací jazyk so silnými typmi, a keď používame autoboxovanie s obalmi, musíme mať na pamäti pár vecí. Nasledujúci kód sa nebude kompilovať:
int primitiveIntNumber = 7; Dvojité wrapperNumber = primitiveIntNumber;
Autoboxing bude fungovať iba s dvojitý
zadajte, pretože to, čo sa stane, keď kompilujete tento kód, je rovnaké ako toto:
Double number = Double.valueOf (primitiveIntNumber);
Vyššie uvedený kód sa skompiluje. Prvýint
typ bude rozšírený na dvojitý
a potom sa to zaškatuľkuje Dvojitý
. Ale pri autoboxe neexistuje rozšírenie typu a konštruktor z Double.valueOf
dostane a dvojitý
, nie int
. V takom prípade by autoboxing fungoval, iba ak by sme použili obsadenie, napríklad takto:
Double wrapperNumber = (double) primitiveIntNumber;
Zapamätaj si toCelé číslo
nemôže byť Dlhé
a Plavák
nemôže byť Dvojitý
. Dedičstvo neexistuje. Každý z týchto typov -Celé číslo
, Dlhé
, Plavák
a Double - je
a Číslo
a an Objekt
.
Ak máte pochybnosti, nezabudnite, že počet obalových súborov je možné rozšíriť na Číslo
alebo Objekt
. (Oobaloch je možné preskúmať oveľa viac, ale to už nechám na iný príspevok.)
Napevno číselne typy čísel v JVM
Keď neurčíme typ na číslo, urobí to za nás JVM. Ak použijeme číslo 1 priamo v kóde, vytvorí ho JVM ako int
. Ak sa pokúsite odovzdať 1 priamo metóde, ktorá prijíma a krátky
, nebude sa kompilovať.
Napríklad:
class Calculator {public static void main (String ... args) {// Táto invokácia tejto metódy sa nebude kompilovať // Áno, 1 môže byť char, short, byte, ale JVM ho vytvorí ako int count (1); } výpočet neplatnosti (krátke číslo) {}}
Rovnaké pravidlo sa použije pri použití čísla 1,0; hoci by to mohlo byť a plavák
, bude JVM považovať toto číslo za a dvojitý
:
class Calculator {public static void main (String ... args) {// Táto invokácia tejto metódy sa nebude kompilovať // Áno, 1 môže byť float, ale JVM ho vytvorí ako dvojitý výpočet (1.0); } výpočet neplatnosti (float number) {}}
Ďalšou častou chybou je myslenie si, že Dvojitý
alebo akýkoľvek iný typ obálky by bol vhodnejší pre metódu, ktorá prijíma a dvojitý
. V skutočnosti to JVM vyžaduje menej úsilia rozširovať the Dvojitý
zavinovačka do Objekt
namiesto rozbalenia do a dvojitý
primitívny typ.
Ak to zhrnieme, pri použití priamo v kóde Java bude 1 int
a 1,0 bude dvojitý
. Rozšírenie je najlenivejšia cesta k prevedeniu, na rad prichádza box alebo unboxing a posledná operácia bude vždy varargs
.
Ako kuriózny fakt ste vedeli, že char
typ prijíma čísla?
char anyChar = 127; // Áno, je to zvláštne, ale kompiluje sa
Čo treba pamätať na preťaženie
Preťaženie je veľmi účinná technika pre scenáre, kde potrebujete rovnaký názov metódy s rôznymi parametrami. Je to užitočná technika, pretože mať správny názov v kóde znamená veľký rozdiel pre čitateľnosť. Namiesto duplikovania metódy a pridania neporiadku do kódu ho môžete jednoducho preťažiť. Vďaka tomu bude váš kód čistý a ľahko čitateľný a zníži sa riziko, že duplicitné metódy rozbijú niektorú časť systému.
Na čo treba pamätať: Pri preťažení metódy vyvinie JVM najmenšie možné úsilie; toto je poradie najlenivejšej cesty k prevedeniu:
- Prvá sa rozširuje
- Druhým je box
- Tretí je Varargs
Na čo si dať pozor: Z bezprostredného vyhlásenia čísla vzniknú zložité situácie: bude int
a 1,0 bude dvojitý
.
Pamätajte tiež, že tieto typy môžete výslovne deklarovať pomocou syntaxe 1F alebo 1f pre a plavák
alebo 1D alebo 1d pre a dvojitý
.
Týmto je ukončený náš prvý Java Challenger, ktorý predstavuje úlohu JVM pri preťažovaní metód. Je dôležité si uvedomiť, že JVM je vo svojej podstate lenivý a bude vždy nasledovať najlenivejšiu cestu k realizácii.
Odpovedať kľúč
Odpoveď na program Java Challenger v zozname 2 je: Možnosť 3. efce.
Viac informácií o preťažení metód v prostredí Java
- Java 101: Triedy a objekty v Jave: Úvod do tried a objektov pre skutočných začiatočníkov vrátane krátkych častí o metódach a preťažení metód.
- Java 101: Základné funkcie jazyka Java: Získajte viac informácií o tom, prečo je dôležité, že jazyk Java je silne písaný, a získajte úplné predstavenie primitívnych typov v jazyku Java.
- Príliš veľa parametrov v metódach Java, časť 4: Preskúmajte obmedzenia a nevýhody preťaženia metód a ako ich možno napraviť integráciou vlastných typov a objektov parametrov.
Tento príbeh „Preťaženie metód v JVM“ pôvodne publikoval server JavaWorld.