Ohjelmointi

Menetelmän ylikuormitus JVM: ssä

Tervetuloa uuteen Java-haastajat blogi! Tämä blogi on omistettu haastaville käsitteille Java-ohjelmoinnissa. Hallitse heidät ja tulet hyvin matkalla kohti korkeasti koulutettua Java-ohjelmoijaa.

Tämän blogin tekniikoiden hallitseminen vaatii jonkin verran ponnisteluja, mutta ne vaikuttavat suuresti päivittäiseen kokemukseesi Java-kehittäjänä. Virheiden välttäminen on helpompaa, kun osaat käyttää Java-ydinohjelmointitekniikoita oikein, ja virheiden jäljittäminen on paljon helpompaa, kun tiedät tarkalleen, mitä Java-koodissasi tapahtuu.

Oletko valmis aloittamaan Java-ohjelmoinnin peruskäsitteiden hallinnan? Aloitetaan sitten ensimmäisen Java Challengerin kanssa!

Terminologia: Menetelmän ylikuormitus

Termin takia ylikuormitus, kehittäjät ajattelevat, että tämä tekniikka ylikuormittaa järjestelmää, mutta se ei ole totta. Ohjelmoinnissa menetelmän ylikuormitus tarkoittaa samaa metodinimeä eri parametreilla.

Mikä on menetelmän ylikuormitus?

Menetelmän ylikuormitus on ohjelmointitekniikka, jonka avulla kehittäjät voivat käyttää samaa metodinimeä useita kertoja samassa luokassa, mutta erilaisilla parametreillä. Tässä tapauksessa sanotaan, että menetelmä on ylikuormitettu. Luettelossa 1 on esitetty yksi menetelmä, jonka parametrit eroavat toisistaan ​​lukumäärän, tyypin ja järjestyksen mukaan.

Listaus 1. Kolme tyyppistä menetelmän ylikuormitusta

 Parametrien lukumäärä: julkisen luokan laskin {tyhjä laskea (int numero1, int luku2) {} void laskea (int numero1, int luku2, int numero3) {}} Parametrien tyyppi: julkinen luokka Laskin {void laskea (int numero1, int numero2) ) {} void calc (kaksinkertainen numero1, kaksinkertainen numero2) {}} Parametrien järjestys: public class Calculator {void calc (double number1, int number2) {} void calc (int number1, double number2) {}} 

Menetelmän ylikuormitus ja primitiiviset tyypit

Luettelossa 1 näet primitiiviset tyypit int ja kaksinkertainen. Työskentelemme enemmän näiden ja muiden tyyppien kanssa, joten ota hetki aikaa tarkistaa Java-alkeelliset tyypit.

Taulukko 1. Primitiiviset tyypit Javassa

TyyppiAlueOletusKokoEsimerkki literaaleista
looginen totta vai tarua väärä 1 bitti totta, väärä
tavu -128 .. 127 0 8 bittiä 1, -90, 128
hiiltyä Unicode-merkki tai 0-65 536 \ u0000 16 bittiä 'a', '\ u0031', '\ 201', '\ n', 4
lyhyt -32,768 .. 32,767 0 16 bittiä 1, 3, 720, 22,000
int -2,147,483,648 .. 2,147,483,647 0 32 bittiä -2, -1, 0, 1, 9
pitkä -9,223,372,036,854,775,808 - 9,223,372,036,854,775,807 0 64 bittiä -4000L, -900L, 10L, 700L
kellua 3,40282347 x 1038, 1,40239846 x 10-45 0.0 32 bittiä 1,67e200f, -1,57e-207f, 0,9f, 10,4F
kaksinkertainen

1,7976931348623157 x 10308, 4,9406564584124654 x 10-324

 0.0 64 bittiä 1. e700d, -123457e, 37e1d

Miksi minun pitäisi käyttää menetelmän ylikuormitusta?

Ylikuormitus tekee koodistasi puhtaamman ja helpommin luettavan, ja se voi myös auttaa välttämään ohjelmiesi virheitä.

Toisin kuin Listing 1, kuvittele ohjelma, jossa sinulla oli useita laskea() menetelmät, joiden nimet ovat laskea1, laskea2, Laske 3 . . . ei hyvä, eikö? Ylikuormittaa laskea() method -menetelmän avulla voit käyttää samaa menetelmän nimeä muuttaessasi vain muutettavaa: parametreja. Ylikuormitettujen menetelmien löytäminen on myös erittäin helppoa, koska ne on ryhmitelty koodissasi.

Mikä ylikuormitus ei ole

Huomaa, että muuttujan nimen muuttaminen ei ole ylikuormitus. Seuraavaa koodia ei koota:

 julkisen luokan laskin {void calc (int firstNumber, int secondNumber) {} void calc (int secondNumber, int thirdNumber) {}} 

Menetelmää ei voi myöskään ylikuormittaa muuttamalla palautustyyppiä menetelmän allekirjoituksessa. Myöskään seuraavaa koodia ei koota:

 julkinen luokka Laskin {kaksoislaskea (int luku1, int luku2) {tuotto 0,0;} pitkä laskea (int luku1, int luku2) {palata 0;}} 

Rakentajan ylikuormitus

Voit ylikuormittaa rakentajaa samalla tavalla kuin menetelmän:

 julkisen luokan laskin {yksityinen int numero1; yksityinen int-numero2; julkinen laskin (int numero1) {tämä.numero1 = luku1;} julkinen laskin (int numero1, int luku2) {tämä.numero1 = luku1; this.numero2 = numero2; }} 

Ota menetelmä ylikuormitushaaste!

Oletko valmis ensimmäiseen Java Challengeriin? Otetaan selvää!

Aloita tarkistamalla seuraava koodi huolellisesti.

Luettelo 2. Edistyneen menetelmän ylikuormitushaaste

 julkinen luokka AdvancedOverloadingChallenge3 {staattinen merkkijono x = ""; public staattinen void main (String ... doYourBest) {executeAction (1); suorittaaAction (1.0); executeAction (Double.valueOf ("5")); suorittaaAction (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 (lyhyt var) {x + = "d"; } static void executeAction (float var) {x + = "e"; } static void executeAction (kaksinkertainen var) {x + = "f"; }} 

Okei, olet tarkistanut koodin. Mikä on tuotos?

  1. kohtaa
  2. bfce
  3. efce
  4. aecf

Tarkista vastauksesi täältä.

Mitä juuri tapahtui? Kuinka JVM kokoaa ylikuormitetut menetelmät

Jotta ymmärtäisit, mitä tapahtui luettelossa 2, sinun on tiedettävä joitain asioita siitä, kuinka JVM kokoaa ylikuormitettuja menetelmiä.

Ensinnäkin JVM on älykkäästi laiska: se ponnistelee aina mahdollisimman vähän menetelmän toteuttamiseksi. Kun siis ajattelet, kuinka JVM käsittelee ylikuormitusta, pidä mielessä kolme tärkeää kääntäjän tekniikkaa:

  1. Levenee
  2. Nyrkkeily (autoboxing ja unboxing)
  3. Varargs

Jos et ole koskaan kohdannut näitä kolmea tekniikkaa, muutaman esimerkin pitäisi auttaa tekemään niistä selvät. Huomaa, että JVM suorittaa ne annetussa järjestyksessä.

Tässä on esimerkki laajenee:

 int primitiivinenIntNumber = 5; double primitiveDoubleNumber = primitiivinenIntNumber; 

Tämä on primitiivisten tyyppien järjestys laajennettuna:

Rafael del Nero

Tässä on esimerkki autoboxing:

 int primitiivinenIntNumber = 7; Kokonaisluku wrapperIntegerNumber = primitiivinenIntNumber; 

Huomaa, mitä tapahtuu kulissien takana, kun tämä koodi käännetään:

 Integer wrapperIntegerNumber = Kokonaisluku.arvoOf (primitiivinenIntNumero); 

Ja tässä on esimerkkipakkauksen avaaminen:

 Kokonaisluku kääreIntegerNumber = 7; int primitiivinenIntNumber = wrapperIntegerNumber; 

Tässä tapahtuu kulissien takana, kun tämä koodi käännetään:

 int primitiivinenIntNumber = wrapperIntegerNumber.intValue (); 

Ja tässä on esimerkki varargs; ota huomioon, että varargs on aina viimeinen suoritettava:

 suorittaa (int… numerot) {} 

Mikä on varargs?

Käytetään muuttujan argumentteihin, varargs on pohjimmiltaan kolmen pisteen määrittämä joukko arvoja (…) Voimme välittää kuinka monta tahansa int numerot, jotka haluamme tähän menetelmään.

Esimerkiksi:

suorittaa (1,3,4,6,7,8,8,6,4,6,88 ...); // Voisimme jatkaa ... 

Varargs on erittäin kätevä, koska arvot voidaan välittää suoraan menetelmälle. Jos käytämme matriiseja, meidän pitäisi instantisoida matriisi arvojen kanssa.

Laajentaminen: Käytännön esimerkki

Kun välitämme numeron 1 suoraan executeAction menetelmä, JVM kohtelee sitä automaattisesti int. Siksi numero ei mene executeAction (lyhyt var) menetelmä.

Vastaavasti, jos välitämme luvun 1.0, JVM tunnistaa kyseisen luvun automaattisesti a: ksi kaksinkertainen.

Tietysti luku 1.0 voi olla myös a kellua, mutta tyyppi on ennalta määritelty. Siksi executeAction (kaksinkertainen var) -menetelmää käytetään luettelossa 2.

Kun käytämme Kaksinkertainen käärintätyypillä on kaksi mahdollisuutta: joko käärinnumeron voi poistaa laatikosta primitiiviseksi tai se voidaan laajentaa Esine. (Muista, että jokainen Java-luokka laajentaa Esine luokassa.) Tällöin JVM päättää laajentaa Kaksinkertainen kirjoita Esine koska se vie vähemmän vaivaa kuin pakkauksen purkaminen vie, kuten selitin aiemmin.

Viimeinen numero, jonka välitämme, on 1 L, ja koska olemme määrittäneet muuttujatyypin tällä kertaa, se on pitkä.

Video-haaste! Virheenkorjausmenetelmän ylikuormitus

Virheenkorjaus on yksi helpoimmista tavoista hyödyntää ohjelmointikonsepteja täysin ja parantaa samalla koodiasi. Tässä videossa voit seurata mukana, kun minä virheenkorjaan ja selitän menetelmän ylikuormitushaastetta:

Yleisiä virheitä ylikuormituksessa

Tähän mennessä olet todennäköisesti tajunnut, että menetelmien ylikuormittumisella voi olla hankalaa, joten tarkastellaan muutamia haasteita, joita todennäköisesti kohtaat.

Autoboxing kääreillä

Java on voimakkaasti kirjoitettu ohjelmointikieli, ja kun käytämme autoboxingia kääreiden kanssa, on pidettävä mielessä joitain asioita. Ensinnäkin seuraavaa koodia ei koota:

 int primitiivinenIntNumber = 7; KaksoiskääreNumero = primitiivinenIntNumber; 

Autoboxing toimii vain kaksinkertainen tyyppi, koska mitä tapahtuu, kun käännät tämän koodin, on sama kuin seuraava:

 Tuplaluku = Tupla.arvoOf (primitiivinenIntNumero); 

Yllä oleva koodi kootaan. Ensimmäinenint tyyppi laajennetaan arvoon kaksinkertainen ja sitten se nyrkkeilee Kaksinkertainen. Mutta kun autoboxing, tyyppiä ei ole laajennettu ja konstruktori siitä Kaksoisarvo saavat a kaksinkertainen, ei int. Tällöin autoboxing toimisi vain, jos käytämme näyttelijöitä, kuten:

 Double wrapperNumber = (kaksinkertainen) primitiivinenIntNumber; 

Muista seKokonaisluku ei voi olla Pitkä ja Kellua ei voi olla Kaksinkertainen. Perintöä ei ole. Jokainen näistä tyypeistä -Kokonaisluku, Pitkä, Kelluaja Tupla - ona Määrä ja Esine.

Jos olet epävarma, muista vain, että kääreiden numerot voidaan laajentaa Määrä tai Esine. (Kääreistä on paljon enemmän tutkittavaa, mutta jätän sen toiseen viestiin.)

Kovakoodatut numerotyypit JVM: ssä

Kun emme määritä numerolle tyyppiä, JVM tekee sen meille. Jos käytämme numeroa 1 suoraan koodissa, JVM luo sen tunnuksena int. Jos yrität välittää 1 suoraan menetelmälle, joka vastaanottaa lyhyt, sitä ei koota.

Esimerkiksi:

 luokan Laskin {public static void main (String… args) {// Tätä menetelmäkutsua ei käännetä // Kyllä, 1 voi olla char, lyhyt, tavu, mutta JVM luo sen int-laskuna (1); } virheellinen laskenta (lyhyt numero) {}} 

Samaa sääntöä käytetään, kun käytetään numeroa 1.0; vaikka se voisi olla kellua, JVM käsittelee tätä lukua a kaksinkertainen:

 luokka Laskin {public static void main (String… args) {// Tätä menetelmäkutsua ei käännetä // Kyllä, 1 voi olla kelluva, mutta JVM luo sen kaksoislaskennana (1.0); } mitätön laskea (kelluva numero) {}} 

Toinen yleinen virhe on ajatella, että Kaksinkertainen tai mikä tahansa muu käärintätyyppi sopisi paremmin menetelmään, joka vastaanottaa a kaksinkertainen. Itse asiassa JVM: n tekeminen vaatii vähemmän vaivaa laajentaa Kaksinkertainen kääre an Esine sen sijaan, että purat sen postilaatikosta a kaksinkertainen primitiivinen tyyppi.

Yhteenvetona voidaan todeta, että kun käytetään suoraan Java-koodissa, yksi tulee olemaan int ja 1.0 ovat kaksinkertainen. Leventäminen on laiskin polku suoritukseen, nyrkkeily tai purkaminen tulee seuraavaksi, ja viimeinen toiminto tulee aina olemaan varargs.

Utelias tosiasia, tiesitkö, että hiiltyä tyyppi hyväksyy numerot?

 char anyChar = 127; // Kyllä, tämä on outoa, mutta se kokoaa 

Mitä muistaa ylikuormituksesta

Ylikuormitus on erittäin tehokas tekniikka tilanteissa, joissa tarvitset saman menetelmän nimen eri parametreilla. Se on hyödyllinen tekniikka, koska oikean nimen käyttäminen koodissasi tekee iso ero luettavuuteen. Sen sijaan, että kopioisit menetelmää ja lisätään sekaannusta koodiin, voit yksinkertaisesti ylikuormittaa sitä. Tämä pitää koodisi puhtaana ja helposti luettavana, ja se vähentää riskiä, ​​että päällekkäiset menetelmät rikkovat osan järjestelmästä.

Mitä pitää mielessä: Menetelmää ylikuormitettaessa JVM tekee mahdollisimman vähän työtä; tämä on kaikkein laiskimman polun toteutus:

  • Ensimmäinen on laajenemassa
  • Toinen on nyrkkeily
  • Kolmas on Varargs

Mitä varoa: Haastavia tilanteita syntyy ilmoittamalla numero suoraan: 1 tulee olemaan int ja 1.0 ovat kaksinkertainen.

Muista myös, että voit ilmoittaa nämä tyypit nimenomaisesti käyttämällä a: n 1F tai 1f syntaksia kellua tai 1D tai 1d a: lle kaksinkertainen.

Tämä päättää ensimmäisen Java Challengerimme, jossa esitellään JVM: n rooli menetelmien ylikuormituksessa. On tärkeää ymmärtää, että JVM on luonnostaan ​​laiska ja seuraa aina kaikkein laiskinta polkua teloitukseen.

 

Vastausavain

Vastaus Java Challengeriin luettelossa 2 on: Vaihtoehto 3. efce.

Lisätietoja Java-menetelmän ylikuormituksesta

  • Java 101: Luokat ja objektit Javassa: Todellinen aloittelijan esittely luokkiin ja objekteihin, mukaan lukien lyhyet osiot menetelmistä ja menetelmien ylikuormituksesta.
  • Java 101: Perustason Java-kieliominaisuudet: Lisätietoja siitä, miksi sillä on merkitystä, että Java on voimakkaasti kirjoitettu kieli, ja tutustu perusteellisesti Java-alkeistyyppeihin.
  • Liian monta parametria Java-menetelmissä, osa 4: Tutustu menetelmien ylikuormituksen rajoituksiin ja haittoihin sekä siihen, miten ne voidaan korjata integroimalla mukautettuja tyyppejä ja parametriobjekteja.

Tämän tarinan "Method overloading in the JVM" julkaisi alun perin JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found