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
Tyyppi | Alue | Oletus | Koko | Esimerkki 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 laskea
1, 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?
- kohtaa
- bfce
- efce
- 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:
- Levenee
- Nyrkkeily (autoboxing ja unboxing)
- 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 NeroTä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ä
, Kellua
ja Tupla - on
a 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.