Dobrodošli v novem Java izzivalci blog! Ta blog je posvečen izzivnim konceptom v programiranju Java. Obvladajte jih in na dobri poti boste postali visoko usposobljeni programer Java.
Tehnike v tem blogu se sicer nekoliko potrudite, vendar bodo zelo vplivale na vaše vsakodnevne izkušnje kot razvijalec Jave. Izogniti se napakam je lažje, če veste, kako pravilno uporabiti osnovne tehnike programiranja Java, sledenje napakam pa je veliko lažje, ko natančno veste, kaj se dogaja na vaši kodi Java.
Ste pripravljeni začeti obvladovati ključne koncepte v programiranju Java? Potem začnimo z našim prvim Java Challengerjem!
Terminologija: Preobremenitev metode
Zaradi izraza preobremenitev, razvijalci ponavadi mislijo, da bo ta tehnika preobremenila sistem, vendar to ni res. Pri programiranju preobremenitev metode pomeni uporabo istega imena metode z različnimi parametri.
Kaj je preobremenitev metode?
Preobremenitev metode je programska tehnika, ki razvijalcem omogoča, da isto ime metode večkrat uporabljajo v istem razredu, vendar z različnimi parametri. V tem primeru pravimo, da je metoda preobremenjena. Seznam 1 prikazuje posamezno metodo, katere parametri se razlikujejo po številu, vrsti in vrstnem redu.
Seznam 1. Tri vrste preobremenitve metode
Število parametrov: kalkulator javnega razreda {void izračun (int število1, int število2) {} void izračuna (int število1, int število2, int število3) {}} Vrsta parametrov: javni razred kalkulator {void izračun (int število1, int število2 ) {} neveljavno izračunavanje (dvojno število1, dvojno število2) {}} Vrstni red parametrov: javni razred Kalkulator {void izračunaj (dvojno število1, int število2) {} neveljavno izračunaj (int število1, dvojno število2) {}}
Preobremenitev metode in primitivni tipi
V seznamu 1 vidite primitivne tipe int
in dvojno
. Delali bomo več s temi in drugimi vrstami, zato si vzemite minuto za pregled primitivnih vrst v Javi.
Tabela 1. Primitivni tipi v Javi
Tip | Doseg | Privzeto | Velikost | Primeri dobesednih besed |
logično | pravilno ali napačno | napačno | 1 bit | pravilno napačno |
bajt | -128 .. 127 | 0 | 8 bitov | 1, -90, 128 |
char | Znak Unicode ali od 0 do 65.536 | \ u0000 | 16 bitov | 'a', '\ u0031', '\ 201', '\ n', 4 |
kratek | -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 |
dolga | -9.223.372.036.854.775.808 do 9.223.372.036.854.775.807 | 0 | 64 bitov | -4000L, -900L, 10L, 700L |
plovec | 3,40282347 x 1038, 1,40239846 x 10-45 | 0.0 | 32 bitov | 1,67e200f, -1,57e-207f, .9f, 10,4F |
dvojno | 1,7976931348623157 x 10308, 4,9406564584124654 x 10-324 | 0.0 | 64 bitov | 1.e700d, -123457e, 37e1d |
Zakaj naj uporabljam preobremenitev metode?
Zaradi preobremenitve je koda čistejša in lažja za branje, prav tako pa vam lahko pomaga, da se izognete napakam v svojih programih.
V nasprotju s seznamom 1 si predstavljajte program, v katerem ste imeli več izračunaj ()
metode z imeni kot izračunajte
1, izračunaj2
, izračunaj3
. . . ni dobro, kajne? Preobremenitev izračunaj ()
metoda vam omogoča, da uporabite isto ime metode, medtem ko spreminjate le tisto, kar je treba spremeniti: parametre. Prav tako je zelo enostavno najti preobremenjene metode, ker so združene v vaši kodi.
Česar preobremenitev ni
Zavedajte se, da spreminjanje imena spremenljivke ni preobremenitev. Naslednja koda ne bo prevedena:
kalkulator javnega razreda {void izračunaj (int firstNumber, int secondNumber) {} neveljavno izračunaj (int secondNumber, int thirdNumber) {}}
Metode tudi ne morete preobremeniti s spreminjanjem vrste vrnitve v podpisu metode. Tudi naslednja koda ne bo prevedena:
javni razred Kalkulator {dvojni izračun (int število1, int število2) {vrnitev 0,0;} dolg izračun (int število1, int število2) {vrnitev 0;}}
Preobremenitev konstruktorja
Konstruktor lahko preobremenite na enak način kot metodo:
javni razred Kalkulator {private int number1; zasebna int številka2; javni kalkulator (int number1) {this.number1 = number1;} javni kalkulator (int number1, int number2) {this.number1 = number1; to.številka2 = število2; }}
Sprejmite izziv preobremenitve metode!
Ste pripravljeni na svoj prvi Java Challenger? Pa ugotovimo!
Najprej natančno preglejte naslednjo kodo.
Seznam 2. Izziv za preobremenitev napredne metode
javni razred AdvancedOverloadingChallenge3 {static String x = ""; javna statična 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 (Integer var) {x + = "b"; } static void executeAction (Object var) {x + = "c"; } static void executeAction (kratka var) {x + = "d"; } static void executeAction (float var) {x + = "e"; } static void executeAction (dvojna var) {x + = "f"; }}
V redu, pregledali ste kodo. Kakšen je rezultat?
- befe
- bfce
- efce
- aecf
Odgovor preverite tukaj.
Kaj se je pravkar zgodilo? Kako JVM prevaja preobremenjene metode
Da bi razumeli, kaj se je zgodilo v seznamu 2, morate vedeti nekaj o tem, kako JVM prevaja preobremenjene metode.
Prvič, JVM je inteligentno len: za izvajanje metode se bo vedno potrudil najmanj. Ko razmišljate o tem, kako JVM obvladuje preobremenitev, upoštevajte tri pomembne tehnike prevajalnika:
- Širjenje
- Boks (avtoboksanje in odpakiranje)
- Varargi
Če se teh treh tehnik še niste srečali, bi vam nekaj primerov pomagalo razjasniti. Upoštevajte, da jih JVM izvrši v danem vrstnem redu.
Tu je primer razširitev:
int primitiveIntNumber = 5; dvojno primitiveDoubleNumber = primitiveIntNumber;
Ta vrstni red primitivnih vrst je razširjen:
Rafael del NeroTu je primer avtoboks:
int primitiveIntNumber = 7; Integer wrapperIntegerNumber = primitiveIntNumber;
Upoštevajte, kaj se zgodi v ozadju, ko je ta koda sestavljena:
Integer wrapperIntegerNumber = Integer.valueOf (primitiveIntNumber);
In tukaj je primerrazpakiranje:
Integer wrapperIntegerNumber = 7; int primitiveIntNumber = wrapperIntegerNumber;
Tu se dogaja v ozadju, ko je ta koda sestavljena:
int primitiveIntNumber = wrapperIntegerNumber.intValue ();
In tukaj je primer varargi; Upoštevajte to varargi
je vedno zadnji, ki se izvede:
izvrši (int… številke) {}
Kaj so varargi?
Uporablja se za spremenljive argumente, varargi
je v bistvu niz vrednosti, določenih s tremi pikami (...) Lahko jih prenesemo toliko int
števila, ki jih želimo tej metodi.
Na primer:
izvrši (1,3,4,6,7,8,8,6,4,6,88 ...); // Lahko bi nadaljevali ...
Varargs je zelo priročen, ker se lahko vrednosti posredujejo neposredno v metodo. Če bi uporabljali polja, bi morali matriko primeriti z vrednostmi.
Širjenje: Praktičen primer
Ko prenesemo številko 1 neposredno na executeAction
JVM samodejno obravnava kot int
. Zato številka ne gre na executeAction (kratka var)
metoda.
Če podamo številko 1.0, JVM to številko samodejno prepozna kot a dvojno
.
Seveda bi lahko bila številka 1.0 tudi plovec
, vendar je vrsta vnaprej določena. Zato executeAction (dvojna var)
metoda je navedena v seznamu 2.
Ko uporabljamo Dvojno
tipu ovoja, obstajata dve možnosti: bodisi številko ovoja je mogoče odstraniti iz primitivnega tipa ali pa jo razširiti v Predmet
. (Ne pozabite, da vsak razred v Javi razširja Predmet
class.) V tem primeru se JVM odloči razširiti Dvojno
vnesite v Predmet
ker zahteva manj napora kot razpakiranje, kot sem že razložil.
Zadnja številka, ki jo posredujemo, je 1L in ker smo tokrat določili vrsto spremenljivke, je dolga
.
Video izziv! Preobremenitev metode odpravljanja napak
Odpravljanje napak je eden najlažjih načinov za popolno absorpcijo konceptov programiranja, hkrati pa izboljšate kodo. V tem videoposnetku lahko spremljate postopek razhroščevanja in razložite izziv preobremenitve metode:
Pogoste napake pri preobremenitvi
Do zdaj ste verjetno že ugotovili, da se lahko s preobremenjenostjo metod zaplete, zato si oglejmo nekaj izzivov, s katerimi se boste verjetno srečali.
Avtoboks z ovoji
Java je močno natipkan programski jezik in pri uporabi samodejnega boksanja z zavitki moramo upoštevati nekaj stvari. Za začetek se naslednja koda ne bo prevedla:
int primitiveIntNumber = 7; Double wrapperNumber = primitiveIntNumber;
Autoboxing bo deloval samo z dvojno
type, kajti zgodi se, ko prevedete to kodo, enako kot naslednje:
Dvojna številka = Double.valueOf (primitiveIntNumber);
Zgornja koda bo sestavljena. Prviint
vrsta bo razširjena na dvojno
in potem bo v boks Dvojno
. Toda pri samodejnem zaboju ni razširitve tipa in konstruktor iz Double.valueOf
bo prejel a dvojno
, ne int
. V tem primeru bi samodejni zaboj deloval le, če bi uporabili igralsko zasedbo, takole:
Double wrapperNumber = (dvojno) primitiveIntNumber;
Zapomni si toCelo število
ne more biti dolga
in Float
ne more biti Dvojno
. Dedovanja ni. Vsaka od teh vrst -Celo število
, dolga
, Float
, in Dvojna - je
a Številka
in an Predmet
.
Če ste v dvomih, samo ne pozabite, da je mogoče številke ovojnic razširiti na Številka
ali Predmet
. (O zavitkih je treba raziskati še veliko več, vendar ga bom pustil za drugo objavo.)
Trdo kodirane vrste številk v JVM
Ko številki ne določimo vrste, bo to naredil JVM namesto nas. Če uporabimo številko 1 neposredno v kodi, jo bo JVM ustvaril kot int
. Če poskusite prenesti 1 neposredno metodi, ki prejema datoteko kratek
, se ne bo prevedel.
Na primer:
class Calculator {public static void main (String ... args) {// Ta klic metode se ne bo prevedel // Da, 1 je lahko char, kratek, bajt, vendar ga JVM ustvari kot int izračun (1); } neveljaven izračun (kratka številka) {}}
Enako pravilo bo veljalo pri uporabi številke 1.0; čeprav bi lahko bil plovec
, bo JVM to številko obravnaval kot dvojno
:
razred Kalkulator {public static void main (String… args) {// Ta klic metode se ne bo prevedel // Da, 1 je lahko float, vendar ga JVM ustvari kot dvojni izračun (1.0); } neveljaven izračun (float številka) {}}
Druga pogosta napaka je misel, da Dvojno
ali katera koli druga vrsta ovitka bi bila bolj primerna za metodo, ki prejema a dvojno
. Pravzaprav JVM potrebuje manj napora razširiti Dvojno
ovoj v Predmet
namesto da bi ga odpakirali v dvojno
primitivni tip.
Če povzamemo, pri neposredni uporabi v kodi Java bo 1 int
in 1.0 bo dvojno
. Razširitev je najbolj lena pot do izvedbe, boksanje ali razpakiranje je na vrsti in zadnja operacija bo vedno varargi
.
Kot nenavadno dejstvo, ali ste vedeli, da char
vrsta sprejema številke?
char anyChar = 127; // Da, to je čudno, vendar se prevaja
Kaj si je treba zapomniti pri preobremenitvi
Preobremenitev je zelo zmogljiva tehnika za scenarije, kjer potrebujete isto ime metode z različnimi parametri. To je uporabna tehnika, saj je ob pravilnem imenu v kodi znak velik razlika za berljivost. Namesto da bi podvojili metodo in kodi dodali nered, jo lahko preprosto preobremenite. S tem boste ohranili svojo kodo čisto in enostavno za branje ter zmanjšali tveganje, da bodo podvojene metode zlomile del sistema.
Kaj je treba upoštevati: Pri preobremenitvi metode se bo JVM potrudil čim manj; to je vrstni red najbolj lene poti do izvedbe:
- Najprej se širi
- Drugi je boks
- Tretji je Varargs
Na kaj paziti: Zapletene situacije se bodo pojavile pri neposredni prijavi številke: 1 bo int
in 1.0 bo dvojno
.
Ne pozabite tudi, da lahko te vrste izrecno deklarirate s sintakso 1F ali 1f za a plovec
ali 1D ali 1d za a dvojno
.
S tem smo zaključili naš prvi Java Challenger in predstavili vlogo JVM pri preobremenitvi metod. Pomembno je vedeti, da je JVM po naravi len in bo vedno sledil najbolj leni poti do usmrtitve.
Tipka za odgovor
Odgovor na Java Challenger v seznamu 2 je: Možnost 3. efce.
Več o preobremenitvi metode v Javi
- Java 101: Razredi in predmeti v Javi: resnični začetniški uvod v razrede in predmete, vključno s kratkimi odseki o metodah in preobremenitvi metod.
- Java 101: Osnovne značilnosti jezika Java: Preberite več o tem, zakaj je pomembno, da je Java močno tipkan jezik, in si oglejte popoln uvod v primitivne vrste v Javi.
- Preveč parametrov v metodah Java, 4. del: Raziščite omejitve in slabosti preobremenitve metode in kako jih je mogoče odpraviti z vključevanjem vrst po meri in objektov parametrov.
To zgodbo, "Preobremenitev metode v JVM", je prvotno objavil JavaWorld.