Velkommen til det nye Java Challengers blogg! Denne bloggen er dedikert til utfordrende konsepter i Java-programmering. Mestre dem, og du vil være godt på vei til å bli en dyktig Java-programmerer.
Teknikkene i denne bloggen krever litt innsats for å mestre, men de vil utgjøre en stor forskjell i din daglige opplevelse som Java-utvikler. Det er lettere å unngå feil når du vet hvordan du skal bruke kjernen i Java-programmeringsteknikker, og sporing av feil er mye lettere når du vet nøyaktig hva som skjer på Java-koden din.
Er du klar til å mestre kjernekonsepter i Java-programmering? La oss så komme i gang med vår første Java Challenger!
Terminologi: Overbelastning av metoden
På grunn av begrepet overbelastning, utviklere har en tendens til å tro at denne teknikken vil overbelaste systemet, men det stemmer ikke. I programmering, metode overbelastning betyr å bruke samme metodenavn med forskjellige parametere.
Hva er metodeoverbelastning?
Metodeoverbelastning er en programmeringsteknikk som lar utviklere bruke samme metodenavn flere ganger i samme klasse, men med forskjellige parametere. I dette tilfellet sier vi at metoden er overbelastet. Oppføring 1 viser en enkelt metode hvis parametere er forskjellige i antall, type og rekkefølge.
Oppføring 1. Tre typer metodeoverbelastning
Antall parametere: offentlig klasse Kalkulator {void calculate (int number1, int number2) {} ugyldig calc (int number1, int number2, int number3) {}} Type parametere: public class Calculator {void calc (int number1, int number2 ) {} ugyldig beregning (dobbelt tall1, dobbelt nummer2) {}} Parameterrekkefølge: offentlig klasse Kalkulator {ugyldig beregning (dobbelt tall1, int tall2) {} ugyldig beregning (int nummer1, dobbelt tall2) {}}
Metodeoverbelastning og primitive typer
I liste 1 ser du de primitive typene int
og dobbelt
. Vi jobber mer med disse og andre typer, så ta et øyeblikk å gjennomgå de primitive typene i Java.
Tabell 1. Primitive typer i Java
Type | Område | Misligholde | Størrelse | Eksempel på bokstaver |
boolsk | sant eller usant | falsk | 1 bit | sant, usant |
byte | -128 .. 127 | 0 | 8 biter | 1, -90, 128 |
røye | Unicode-tegn eller 0 til 65.536 | \ u0000 | 16 bits | 'a', '\ u0031', '\ 201', '\ n', 4 |
kort | -32,768 .. 32,767 | 0 | 16 bits | 1, 3, 720, 22,000 |
int | -2,147,483,648 .. 2,147,483,647 | 0 | 32 biter | -2, -1, 0, 1, 9 |
lang | -9,223,372,036,854,775,808 til 9,223,372,036,854,775,807 | 0 | 64 bits | -4000L, -900L, 10L, 700L |
flyte | 3.40282347 x 1038, 1.40239846 x 10-45 | 0.0 | 32 biter | 1.67e200f, -1.57e-207f, .9f, 10.4F |
dobbelt | 1.7976931348623157 x 10308, 4.9406564584124654 x 10-324 | 0.0 | 64 bits | 1.e700d, -123457e, 37e1d |
Hvorfor skal jeg bruke metodeoverbelastning?
Overbelastning gjør koden renere og lettere å lese, og det kan også hjelpe deg med å unngå feil i programmene dine.
I motsetning til oppføring 1, forestill deg et program der du hadde flere regne ut()
metoder med navn som regne ut
1, beregne2
, beregne3
. . . ikke bra, ikke sant? Overbelastning av regne ut()
metoden lar deg bruke samme metodenavn mens du bare endrer det som må endres: parametrene. Det er også veldig enkelt å finne overbelastede metoder fordi de er gruppert sammen i koden din.
Hva overbelastning er ikke
Vær oppmerksom på at du endrer navnet på en variabel er ikke overbelastning. Følgende kode kompileres ikke:
offentlig klasse Kalkulator {void calculate (int firstNumber, int secondNumber) {} void calculate (int secondNumber, int thirdNumber) {}}
Du kan heller ikke overbelaste en metode ved å endre returtypen i metodesignaturen. Følgende kode vil heller ikke kompileres:
offentlig klasse Kalkulator {dobbel beregne (int tall1, int tall2) {retur 0,0;} lang beregne (int tall1, int nummer2) {retur 0;}}
Overbelastning av konstruktør
Du kan overbelaste en konstruktør på samme måte som en metode:
offentlig klasse Kalkulator {privat int nummer1; privat int nummer2; public Calculator (int number1) {this.number1 = number1;} public Calculator (int number1, int number2) {this.number1 = number1; dette.nummer2 = nummer2; }}
Ta metoden overbelastning utfordring!
Er du klar for din første Java Challenger? La oss finne det ut!
Start med å nøye gjennomgå følgende kode.
Oppføring 2. Avansert metode for overbelastningsutfordring
offentlig klasse AdvancedOverloadingChallenge3 {statisk streng x = ""; public static void main (String ... doYourBest) {executeAction (1); executeAction (1.0); executeAction (Double.valueOf ("5")); executeAction (1L); System.out.println (x); } statisk tomrom executeAction (int ... var) {x + = "a"; } statisk tomrom executeAction (Heltall var) {x + = "b"; } statisk tomrom executeAction (Object var) {x + = "c"; } statisk tomrom executeAction (kort var) {x + = "d"; } statisk tomrom executeAction (float var) {x + = "e"; } statisk tomrom executeAction (dobbel var) {x + = "f"; }}
Ok, du har vurdert koden. Hva er produksjonen?
- befe
- bfce
- efce
- aecf
Sjekk svaret ditt her.
Hva skjedde nå? Hvordan JVM kompilerer overbelastede metoder
For å forstå hva som skjedde i Listing 2, må du vite noen ting om hvordan JVM kompilerer overbelastede metoder.
Først av alt er JVM det intelligent lat: det vil alltid anstrenge seg minst mulig for å utføre en metode. Når du tenker på hvordan JVM håndterer overbelastning, må du huske på tre viktige kompileringsteknikker:
- Utvidende
- Boksing (autoboksing og unboxing)
- Varargs
Hvis du aldri har møtt disse tre teknikkene, bør noen få eksempler bidra til å gjøre dem tydelige. Merk at JVM utfører dem i bestillingen gitt.
Her er et eksempel på utvidende:
int primitiveIntNumber = 5; dobbelt primitiveDoubleNumber = primitiveIntNumber;
Dette er rekkefølgen til de primitive typene når de utvides:
Rafael del NeroHer er et eksempel på autoboksing:
int primitiveIntNumber = 7; Integer wrapperIntegerNumber = primitiveIntNumber;
Legg merke til hva som skjer bak kulissene når denne koden blir samlet:
Integer wrapperIntegerNumber = Integer.valueOf (primitiveIntNumber);
Og her er et eksempel påunboxing:
Integer wrapperIntegerNumber = 7; int primitiveIntNumber = wrapperIntegerNumber;
Dette er hva som skjer bak kulissene når denne koden blir samlet:
int primitiveIntNumber = wrapperIntegerNumber.intValue ();
Og her er et eksempel på varargs; noter det varargs
er alltid den siste som blir henrettet:
utfør (int ... tall) {}
Hva er Varargs?
Brukes til variable argumenter, varargs
er i utgangspunktet en rekke verdier spesifisert av tre prikker (...) Vi kan passere hvor mange som helst int
tallene vi ønsker å denne metoden.
For eksempel:
utføre (1,3,4,6,7,8,8,6,4,6,88 ...); // Vi kunne fortsette ...
Varargs er veldig nyttig fordi verdiene kan overføres direkte til metoden. Hvis vi brukte matriser, måtte vi samle arrayet med verdiene.
Utvidelse: Et praktisk eksempel
Når vi sender nummer 1 direkte til executeAction
metode, behandler JVM den automatisk som en int
. Det er derfor tallet ikke går til executeAction (kort var)
metode.
På samme måte, hvis vi passerer tallet 1.0, gjenkjenner JVM automatisk tallet som et dobbelt
.
Selvfølgelig kan tallet 1.0 også være en flyte
, men typen er forhåndsdefinert. Det er derfor executeAction (dobbel var)
metoden blir påkalt i Listing 2.
Når vi bruker Dobbelt
innpakningstype, det er to muligheter: enten innpakningsnummeret kan være utpakket til en primitiv type, eller det kan utvides til en Gjenstand
. (Husk at hver klasse i Java utvider Gjenstand
klasse.) I så fall velger JVM å utvide Dobbelt
skriv til en Gjenstand
fordi det krever mindre innsats enn unboxing ville, som jeg forklarte tidligere.
Det siste tallet vi passerer er 1 liter, og fordi vi har spesifisert variabeltypen denne gangen, er det det lang
.
Videoutfordring! Feilsøking metode overbelastning
Feilsøking er en av de enkleste måtene å fullt ut absorbere programmeringskonsepter samtidig som du forbedrer koden din. I denne videoen kan du følge med mens jeg feilsøker og forklarer metoden for overbelastningsutfordring:
Vanlige feil med overbelastning
Nå har du sannsynligvis funnet ut at ting kan bli vanskelig med overbelastning av metoden, så la oss vurdere noen av utfordringene du sannsynligvis vil møte.
Autoboksing med innpakninger
Java er et sterkt skrevet programmeringsspråk, og når vi bruker autoboksing med innpakninger, er det noen ting vi må huske på. For det første kompileres ikke følgende kode:
int primitiveIntNumber = 7; Dobbelt wrapperNumber = primitiveIntNumber;
Autoboksing fungerer bare med dobbelt
skriv fordi det som skjer når du kompilerer denne koden er det samme som følgende:
Dobbeltnummer = Double.valueOf (primitiveIntNumber);
Ovennevnte kode vil kompilere. Den førsteint
typen blir utvidet til dobbelt
og så blir det bokset til Dobbelt
. Men når autoboksing er det ingen type utvidelse og konstruktøren fra Double.valueOf
vil motta en dobbelt
, ikke en int
. I dette tilfellet vil autoboksing bare fungere hvis vi bruker en rollebesetting, slik:
Double wrapperNumber = (double) primitiveIntNumber;
Husk atHeltall
Kan ikke være Lang
og Flyte
Kan ikke være Dobbelt
. Det er ingen arv. Hver av disse typene--Heltall
, Lang
, Flyte
, og Dobbelt - er
en Nummer
og en Gjenstand
.
Når du er i tvil, er det bare å huske at innpakningstallene kan utvides til Nummer
eller Gjenstand
. (Det er mye mer å utforske om innpakninger, men jeg vil legge igjen det til et annet innlegg.)
Hardkodede nummertyper i JVM
Når vi ikke spesifiserer en type til et tall, vil JVM gjøre det for oss. Hvis vi bruker nummer 1 direkte i koden, vil JVM opprette det som et int
. Hvis du prøver å gi 1 direkte til en metode som mottar en kort
, vil den ikke kompilere.
For eksempel:
class Calculator {public static void main (String ... args) {// Denne metoden kan ikke kompileres // Ja, 1 kan være char, kort, byte, men JVM oppretter den som en int-beregning (1); } ugyldig beregne (kort tall) {}}
Den samme regelen blir brukt når du bruker tallet 1.0; selv om det kan være en flyte
, vil JVM behandle dette tallet som en dobbelt
:
class Calculator {public static void main (String ... args) {// Denne metoden kan ikke kompileres // Ja, 1 kan være flytende, men JVM oppretter den som dobbeltberegning (1.0); } ugyldig beregning (flytnummer) {}}
En annen vanlig feil er å tro at Dobbelt
eller hvilken som helst annen innpakningstype, vil være bedre egnet til metoden som mottar en dobbelt
. Det tar faktisk mindre innsats for JVM å utvide de Dobbelt
innpakning til en Gjenstand
i stedet for å pakke den ut til en dobbelt
primitiv type.
For å oppsummere, når det brukes direkte i Java-kode, vil 1 være int
og 1.0 vil være dobbelt
. Utvidelse er den lateste veien til utførelse, boksing eller unboxing kommer neste, og den siste operasjonen vil alltid være varargs
.
Som et merkelig faktum, visste du at røye
type aksepterer tall?
char anyChar = 127; // Ja, dette er rart, men det kompilerer
Hva du skal huske på overbelastning
Overbelastning er en veldig kraftig teknikk for scenarier der du trenger samme metodenavn med forskjellige parametere. Det er en nyttig teknikk fordi det å ha det riktige navnet i koden din stor forskjell for lesbarhet. I stedet for å duplisere metoden og legge til rot i koden din, kan du bare overbelaste den. Å gjøre dette holder koden ren og lett å lese, og det reduserer risikoen for at duplikatmetoder vil ødelegge en del av systemet.
Hva du må huske på: Ved overbelastning av en metode vil JVM gjøre minst mulig innsats; dette er rekkefølgen på den lateste veien til henrettelse:
- Først utvides
- For det andre er boksing
- Tredje er Varargs
Hva du skal passe på: Vanskelige situasjoner vil oppstå ved å erklære et nummer direkte: 1 vil være int
og 1.0 blir dobbelt
.
Husk også at du kan erklære disse typene eksplisitt ved hjelp av syntaksen 1F eller 1f for a flyte
eller 1D eller 1d for en dobbelt
.
Dette avslutter vår første Java Challenger, der vi introduserer JVMs rolle i metodeoverbelastning. Det er viktig å innse at JVM er iboende lat, og alltid vil følge den lateste veien til henrettelse.
Fasit
Svaret på Java Challenger i Listing 2 er: Alternativ 3. efce.
Mer om metodeoverbelastning i Java
- Java 101: Klasser og objekter i Java: En ekte nybegynnerintroduksjon til klasser og objekter, inkludert korte seksjoner om metoder og metodeoverbelastning.
- Java 101: Elementære Java-språkfunksjoner: Lær mer om hvorfor det betyr noe at Java er et sterkt skrevet språk og få en full introduksjon til primitive typer i Java.
- For mange parametere i Java-metoder, del 4: Utforsk begrensningene og ulempene ved metodeoverbelastning, og hvordan de kan løses ved å integrere tilpassede typer og parameterobjekter.
Denne historien, "Method overloading in the JVM" ble opprinnelig utgitt av JavaWorld.