Velkommen til det nye Java udfordrere blog! Denne blog er dedikeret til udfordrende koncepter inden for Java-programmering. Mestre dem, og du vil være godt på vej til at blive en meget dygtig Java-programmør.
Teknikkerne i denne blog kræver en vis indsats for at mestre, men de vil gøre en stor forskel i din daglige oplevelse som Java-udvikler. Det er lettere at undgå bugs, når du ved, hvordan du korrekt anvender Java-programmeringsteknikker korrekt, og det er meget lettere at spore bugs, når du ved præcis, hvad der sker på din Java-kode.
Er du klar til at begynde at mestre kernekoncepter i Java-programmering? Lad os så komme i gang med vores første Java Challenger!
Terminologi: Metodeoverbelastning
På grund af udtrykket overbelastning, udviklere har tendens til at tro, at denne teknik vil overbelaste systemet, men det er ikke sandt. I programmering, metode overbelastning betyder at bruge samme metode navn med forskellige parametre.
Hvad er metodeoverbelastning?
Metodeoverbelastning er en programmeringsteknik, der giver udviklere mulighed for at bruge det samme metodenavn flere gange i samme klasse, men med forskellige parametre. I dette tilfælde siger vi, at metoden er overbelastet. Liste 1 viser en enkelt metode, hvis parametre adskiller sig i antal, type og rækkefølge.
Notering 1. Tre typer metodeoverbelastning
Antal parametre: offentlig klasse Lommeregner {ugyldig beregning (int nummer1, int nummer2) {} ugyldig beregning (int nummer1, int antal2, int nummer3) {}} Parametertype: offentlig klasse regnemaskine {ugyldig beregning (int nummer1, int nummer2 ) {} ugyldig beregning (dobbelt nummer1, dobbelt tal2) {}} Parameterrækkefølge: offentlig klasse-regnemaskine
Metodeoverbelastning og primitive typer
I liste 1 ser du de primitive typer int
og dobbelt
. Vi arbejder mere med disse og andre typer, så tag et øjeblik på at gennemgå de primitive typer i Java.
Tabel 1. Primitive typer i Java
Type | Rækkevidde | Standard | Størrelse | Eksempel på bogstaver |
boolsk | sandt eller falsk | falsk | 1 bit | sandt falsk |
byte | -128 .. 127 | 0 | 8 bits | 1, -90, 128 |
char | 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 bits | -2, -1, 0, 1, 9 |
lang | -9.223.372.036.854.775.808 til 9.223.372.036.854.775.807 | 0 | 64 bit | -4000L, -900L, 10L, 700L |
flyde | 3.40282347 x 1038, 1.40239846 x 10-45 | 0.0 | 32 bits | 1,67e200f, -1,57e-207f, .9f, 10,4F |
dobbelt | 1.7976931348623157 x 10308, 4.9406564584124654 x 10-324 | 0.0 | 64 bit | 1.e700d, -123457e, 37e1d |
Hvorfor skal jeg bruge metodeoverbelastning?
Overbelastning gør din kode renere og lettere at læse, og det kan også hjælpe dig med at undgå fejl i dine programmer.
I modsætning til liste 1, forestil dig et program, hvor du havde flere Beregn()
metoder med navne som Beregn
1, beregne2
, beregne3
. . . ikke godt, ikke? Overbelastning af Beregn()
metode lader dig bruge det samme metodenavn, mens du kun ændrer det, der skal ændres: parametrene. Det er også meget let at finde overbelastede metoder, fordi de er samlet i din kode.
Hvilken overbelastning er ikke
Vær opmærksom på, at du ændrer navnet på en variabel er ikke overbelastning. Følgende kode kompileres ikke:
offentlig klasse Lommeregner {ugyldig beregne (int firstNumber, int secondNumber) {} ugyldig beregne (int secondNumber, int thirdNumber) {}}
Du kan heller ikke overbelaste en metode ved at ændre returtypen i metodesignaturen. Den følgende kode kompileres heller ikke:
offentlig klasse Lommeregner {dobbeltberegning (int-nummer1, int-nummer2) {returnering 0,0;} lang beregning (int-nummer1, int-nummer2) {retur 0;}}
Konstruktør overbelastning
Du kan overbelaste en konstruktør på samme måde som en metode:
public class Calculator {privat int nummer1; privat int nummer2; public Calculator (int number1) {this.number1 = number1;} public Calculator (int number1, int number2) {this.number1 = number1; dette.nummer2 = antal2; }}
Tag metoden overbelastning udfordring!
Er du klar til din første Java Challenger? Lad os finde ud af det!
Start med nøje at gennemgå følgende kode.
Notering 2. Avanceret metode til overbelastningsudfordring
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 ugyldighed executeAction (int ... var) {x + = "a"; } statisk ugyldighed executeAction (heltal var) {x + = "b"; } statisk ugyldighed executeAction (Objekt var) {x + = "c"; } statisk ugyldighed executeAction (kort var) {x + = "d"; } statisk ugyldighed executeAction (float var) {x + = "e"; } statisk ugyldighed executeAction (dobbelt var) {x + = "f"; }}
Okay, du har gennemgået koden. Hvad er output?
- befe
- bfce
- efce
- aecf
Tjek dit svar her.
Hvad skete der lige? Hvordan JVM kompilerer overbelastede metoder
For at forstå hvad der skete i Listing 2, skal du vide nogle ting om, hvordan JVM kompilerer overbelastede metoder.
Først og fremmest er JVM det intelligent doven: det vil altid udøve mindst mulig indsats for at udføre en metode. Når du overvejer, hvordan JVM håndterer overbelastning, skal du huske på tre vigtige kompileringsteknikker:
- Udvidelse
- Boksning (autoboxing og unboxing)
- Varargs
Hvis du aldrig har stødt på disse tre teknikker, bør et par eksempler hjælpe med at gøre dem klare. Bemærk, at JVM udfører dem i den angivne rækkefølge.
Her er et eksempel på udvidelse:
int primitiveIntNumber = 5; dobbelt primitiveDoubleNumber = primitiveIntNumber;
Dette er rækkefølgen af de primitive typer, når de udvides:
Rafael del NeroHer er et eksempel på autoboxing:
int primitiveIntNumber = 7; Integer wrapperIntegerNumber = primitiveIntNumber;
Bemærk hvad der sker bag kulisserne, når denne kode er kompileret:
Integer wrapperIntegerNumber = Integer.valueOf (primitiveIntNumber);
Og her er et eksempel påunboxing:
Integer wrapperIntegerNumber = 7; int primitiveIntNumber = wrapperIntegerNumber;
Her er hvad der sker bag kulisserne, når denne kode er kompileret:
int primitiveIntNumber = wrapperIntegerNumber.intValue ();
Og her er et eksempel på varargs; Noter det varargs
er altid den sidste, der udføres:
udfør (int ... numre) {}
Hvad er varargs?
Bruges til variable argumenter, varargs
er dybest set en række værdier, der er specificeret af tre prikker (...) Vi kan passere, hvor mange som helst int
tal, vi ønsker at denne metode.
For eksempel:
udføre (1,3,4,6,7,8,8,6,4,6,88 ...); // Vi kunne fortsætte ...
Varargs er meget praktisk, fordi værdierne kan overføres direkte til metoden. Hvis vi brugte arrays, ville vi være nødt til at instantiere arrayet med værdierne.
Udvidelse: Et praktisk eksempel
Når vi sender nummer 1 direkte til executeAction
metode behandler JVM den automatisk som en int
. Derfor går antallet ikke til executeAction (kort var)
metode.
Tilsvarende, hvis vi videregiver nummeret 1.0, genkender JVM automatisk dette nummer som et dobbelt
.
Naturligvis kan tallet 1.0 også være en flyde
, men typen er foruddefineret. Det er derfor executeAction (dobbelt var)
metode påberåbes i liste 2.
Når vi bruger Dobbelt
indpakningstype, der er to muligheder: enten indpakningsnummeret kunne være udpakket til en primitiv type, eller det kunne udvides til en Objekt
. (Husk at hver klasse i Java udvider Objekt
klasse.) I så fald vælger JVM at udvide Dobbelt
skriv til en Objekt
fordi det kræver mindre indsats end unboxing ville, som jeg forklarede før.
Det sidste tal, vi videregiver, er 1 liter, og fordi vi har specificeret variabeltypen denne gang, er det lang
.
Video udfordring! Fejlretningsmetode overbelastning
Fejlfinding er en af de nemmeste måder til fuldt ud at absorbere programmeringskoncepter, samtidig med at du forbedrer din kode. I denne video kan du følge med, mens jeg debugger og forklarer metoden for overbelastningsudfordring:
Almindelige fejl med overbelastning
Nu har du sandsynligvis fundet ud af, at ting kan blive vanskelige med overbelastning af metoder, så lad os overveje et par af de udfordringer, du sandsynligvis vil støde på.
Autoboxing med indpakninger
Java er et stærkt skrevet programmeringssprog, og når vi bruger autoboxing med indpakninger, er der nogle ting, vi skal huske på. For det første kompileres følgende kode ikke:
int primitiveIntNumber = 7; Dobbelt wrapperNumber = primitiveIntNumber;
Autoboxing fungerer kun med dobbelt
skriv, fordi hvad der sker, når du kompilerer denne kode, er det samme som følgende:
Dobbeltnummer = Double.valueOf (primitiveIntNumber);
Ovenstående kode kompileres. Den førsteint
type udvides til dobbelt
og så vil det blive bokset til Dobbelt
. Men når autoboxing er der ingen type udvidelse, og konstruktøren fra Double.valueOf
modtager en dobbelt
, ikke en int
. I dette tilfælde fungerer autoboxing kun, hvis vi anvender en rollebesætning, sådan:
Double wrapperNumber = (dobbelt) primitiveIntNumber;
Huske på, atHeltal
kan ikke være Lang
og Flyde
kan ikke være Dobbelt
. Der er ingen arv. Hver af disse typer--Heltal
, Lang
, Flyde
og Dobbelt - er
-en Nummer
og en Objekt
.
Når du er i tvivl, skal du bare huske at indpakningsnumrene kan udvides til Nummer
eller Objekt
. (Der er meget mere at udforske om indpakninger, men jeg vil lade det være til et andet indlæg.)
Hårdkodede nummertyper i JVM
Når vi ikke angiver en type til et nummer, vil JVM gøre det for os. Hvis vi bruger nummer 1 direkte i koden, opretter JVM det som et int
. Hvis du prøver at videregive 1 direkte til en metode, der modtager en kort
, det kompilerer ikke.
For eksempel:
class Calculator {public static void main (String… args) {// Denne metodeopkald kompileres ikke // Ja, 1 kunne være char, kort, byte, men JVM opretter den som en int-beregning (1); } ugyldigt beregne (kort tal) {}}
Den samme regel anvendes, når du bruger tallet 1.0; selvom det kunne være en flyde
, JVM behandler dette nummer som en dobbelt
:
class Calculator {public static void main (String ... args) {// Denne metodeopkald vil ikke kompilere // Ja, 1 kunne være float, men JVM opretter det som dobbeltberegning (1.0); } ugyldigt beregne (flydende nummer) {}}
En anden almindelig fejl er at tro, at Dobbelt
eller enhver anden indpakningstype ville være bedre egnet til den metode, der modtager en dobbelt
. Faktisk tager det mindre indsats for JVM at udvide det Dobbelt
indpakning til en Objekt
i stedet for at afkasse den til en dobbelt
primitiv type.
For at opsummere, når det bruges direkte i Java-kode, vil 1 være int
og 1.0 vil være dobbelt
. Udvidelse er den lateste vej til udførelse, boksning eller unboxing kommer derefter, og den sidste handling vil altid være varargs
.
Som en underlig kendsgerning vidste du, at char
type accepterer tal?
char anyChar = 127; // Ja, dette er underligt, men det kompilerer
Hvad man skal huske om overbelastning
Overbelastning er en meget kraftfuld teknik til scenarier, hvor du har brug for det samme metodenavn med forskellige parametre. Det er en nyttig teknik, fordi det at have det rigtige navn i din kode er en stor forskel for læsbarhed. I stedet for at duplikere metoden og tilføje rod til din kode, kan du simpelthen overbelaste den. Hvis du gør dette, holder din kode ren og let at læse, og det reducerer risikoen for, at duplikatmetoder bryder en del af systemet.
Hvad man skal huske på: Ved overbelastning af en metode vil JVM gøre mindst mulig indsats; dette er rækkefølgen af den lateste vej til henrettelse:
- Først udvides
- Andet er boksning
- Tredje er Varargs
Hvad man skal passe på: Tricky situationer vil opstå ved at erklære et nummer direkte: 1 vil være int
og 1.0 vil være dobbelt
.
Husk også, at du eksplicit kan erklære disse typer ved hjælp af syntaksen 1F eller 1f for a flyde
eller 1D eller 1d for en dobbelt
.
Dette afslutter vores første Java Challenger, der introducerer JVM's rolle i metodeoverbelastning. Det er vigtigt at indse, at JVM iboende er doven og altid vil følge den lateste vej til henrettelse.
Svar nøgle
Svaret på Java Challenger i Listing 2 er: Option 3. efce.
Mere om metodeoverbelastning i Java
- Java 101: Klasser og objekter i Java: En ægte begynders introduktion til klasser og objekter, herunder korte sektioner om metoder og metodeoverbelastning.
- Java 101: Elementære Java-sprogfunktioner: Lær mere om, hvorfor det betyder noget, at Java er et stærkt skrevet sprog, og få en fuld introduktion til primitive typer i Java.
- For mange parametre i Java-metoder, del 4: Undersøg begrænsningerne og ulemperne ved metodeoverbelastning, og hvordan de kan afhjælpes ved at integrere brugerdefinerede typer og parameterobjekter.
Denne historie, "Metodeoverbelastning i JVM", blev oprindeligt udgivet af JavaWorld.