Sadrži li potpis metode metodu vrste povrata u Javi?

1. Pregled

Potpis metode samo je podskup cijele definicije metode u Javi. Stoga točna anatomija potpisa može izazvati zabunu.

U ovom uputstvu naučit ćemo elemente potpisa metode i njihove implikacije na Java programiranje.

2. Potpis metode

Metode u Javi podržavaju preopterećenje, što znači da se više metoda s istim imenom može definirati u istoj klasi ili hijerarhiji klasa. Stoga prevoditelj mora biti u stanju statički vezati metodu na koju se odnosi klijentski kod. Iz tog razloga, metoda potpis jedinstveno identificira svaku metodu.

Prema Oracleu, metoda potpis se sastoji od imena i tipova parametara. Stoga svi ostali elementi deklaracije metode, poput modifikatora, tipa povratka, imena parametara, popisa izuzetaka i tijela nisu dio potpisa.

Pogledajmo bliže preopterećenosti metode i kako se ona odnosi na potpise metode.

3. Pogreške preopterećenja

Razmotrimo sljedeći kod:

public void print () {System.out.println ("Potpis je: print ()"); } javni void ispis (int parametar) {System.out.println ("Potpis je: print (int)"); }

Kao što vidimo, kod se kompajlira jer metode imaju različite popise vrsta parametara. Zapravo, kompajler može deterministički vezati bilo koji poziv za jedan ili drugi.

Sad provjerimo je li dopušteno preopterećivanje dodavanjem sljedeće metode:

public int print () {System.out.println ("Potpis je: print ()"); povratak 0; }

Kada kompajliramo, dobit ćemo pogrešku "metoda je već definirana u klasi". To dokazuje metodu tip povratka nije dio potpisa metode.

Pokušajmo isto s modifikatorima:

privatni konačni void print () {System.out.println ("Potpis je: print ()"); }

Još uvijek vidimo istu grešku "metoda je već definirana u klasi". Stoga metoda potpis ne ovisi o modifikatorima.

Preopterećenje promjenom izbačenih iznimaka može se testirati dodavanjem:

public void print () baca IllegalStateException {System.out.println ("Potpis je: print ()"); baci novi IllegalStateException (); }

Opet vidimo pogrešku "metoda je već definirana u klasi", koja ukazuje na Izjava o bacanju ne može biti dio potpisa.

Posljednje što možemo testirati jest dopušta li promjena naziva parametara preopterećenje. Dodajmo sljedeću metodu:

javni void ispis (int anotherParameter) {System.out.println ("Potpis je: print (int)"); }

Kao što se i očekivalo, dobivamo istu pogrešku pri kompilaciji. Ovo znači to imena parametara ne utječu na potpis metode.

3. Generički podaci i brisanje tipova

S generičkim parametrima, brisanje tipa mijenja efektivni potpis. U stvari, to može uzrokovati koliziju s drugom metodom koja koristi gornju granicu generičkog tipa umjesto generičkog tokena.

Razmotrimo sljedeći kod:

javna klasa OverloadingErrors {public void printElement (T t) {System.out.println ("Potpis je: printElement (T)"); } public void printElement (Serializable o) {System.out.println ("Potpis je: printElement (Serializable)"); }}

Iako se potpisi čine drugačijima, prevoditelj ne može statički povezati ispravnu metodu nakon brisanja tipa.

Možemo vidjeti kako kompajler zamjenjuje T s gornjom granicom, Serializirati, zbog brisanja tipa. Dakle, sukobljava se s metodom koja se eksplicitno koristi Serijalizirati.

Isti rezultat vidjeli bismo i kod osnovnog tipa Objekt kad generički tip nema vezu.

4. Popisi parametara i polimorfizam

Potpis metode uzima u obzir točne vrste. To znači da možemo preopteretiti metodu čiji je tip parametra podrazred ili superrazred.

Međutim, moramo obratiti posebnu pažnju kao statičko vezivanje pokušat će se podudarati pomoću polimorfizma, automatskog boksa i promocije tipa.

Pogledajmo sljedeći kod:

zbroj javnog broja (cjeloviti pojam1, cjeloviti pojam2) {System.out.println ("Dodavanje cijelih brojeva"); povratni pojam1 + pojam2; } zbroj javnih brojeva (broj pojam1, broj pojam2) {System.out.println ("Dodavanje brojeva"); vratiti term1.doubleValue () + term2.doubleValue (); } zbroj javnog broja (pojam objekta1, pojam objekta2) {System.out.println ("Dodavanje objekata"); vratiti term1.hashCode () + term2.hashCode (); }

Gornji kod je potpuno legalan i sastavit će se. Zbrka može nastati prilikom pozivanja ovih metoda jer ne samo da moramo znati točan potpis metode koji zovemo već i kako se Java statički veže na temelju stvarnih vrijednosti.

Istražimo nekoliko poziva metode koji su na kraju vezani zbroj (Integer, Integer):

StaticBinding obj = novi StaticBinding (); obj.sum (Integer.valueOf (2), Integer.valueOf (3)); obj.sum (2, 3); obj.sum (2, 0x1);

Za prvi poziv imamo točne vrste parametara Cijeli broj, cijeli broj. Pri drugom pozivu Java će se automatski potvrditi int do Cijeli broj za nas. I na kraju, Java će transformirati vrijednost bajta 0x1 do int pomoću promocije tipa, a zatim je automatski označite Cijeli broj.

Slično tome, imamo sljedeće pozive koji se vežu za zbroj (broj, broj):

obj.sum (2.0d, 3.0d); obj.sum (Float.valueOf (2), Float.valueOf (3));

Na prvi poziv jesmo dvostruko vrijednosti na koje se automatski uokviruje Dvostruko. A onda, pomoću polimorfizma, Dvostruko šibice Broj. Identično, Plutati šibice Broj za drugi poziv.

Promotrimo činjenicu da oboje Plutati i Dvostruko naslijediti od Broj i Objekt. Međutim, zadano vezivanje je za Broj. To je zbog činjenice da će se Java automatski podudarati s najbližim super-vrstama koje odgovaraju potpisu metode.

Sada razmotrimo sljedeći poziv metode:

obj.sum (2, "Ivan");

U ovom primjeru imamo int do Cijeli broj automatski okvir za prvi parametar. Međutim, ne postoji zbroj (cijeli broj, niz) preopterećenje za naziv ove metode. Slijedom toga, Java će prolaziti kroz sve supertipove parametara koje će emitirati od najbližeg roditelja Objekt dok ne nađe podudaranje. U ovom se slučaju veže na zbroj (Objekt, Objekt).

Da bismo promijenili zadano vezivanje, možemo koristiti eksplicitno lijevanje parametara kako slijedi:

obj.sum ((Objekt) 2, (Objekt) 3); obj.sum ((Broj) 2, (Broj) 3);

5. Vararg parametri

Sada ćemo skrenuti pozornost na to kako varargi utjecati na učinkovit potpis metode i statičko vezivanje.

Ovdje imamo preopterećenu metodu koja koristi varargi:

zbroj javnih brojeva (Object term1, Object term2) {System.out.println ("Dodavanje objekata"); vratiti term1.hashCode () + term2.hashCode (); } zbroj javnog broja (Object term1, Object ... term2) {System.out.println ("Dodavanje argumenata varijable:" + term2.length); int rezultat = term1.hashCode (); za (Objekt o: pojam2) {rezultat + = o.hashCode (); } vratiti rezultat; }

Pa koji su učinkoviti potpisi metoda? To smo već vidjeli zbroj (objekt, objekt) je potpis za prvi. Varijabilni argumenti su u osnovi nizovi, pa je učinkoviti potpis za drugi nakon kompilacije zbroj (Objekt, Objekt []).

Škakljivo je pitanje kako možemo odabrati vezanje metode kad imamo samo dva parametra?

Razmotrimo sljedeće pozive:

obj.sum (novi objekt (), novi objekt ()); obj.sum (novi objekt (), novi objekt (), novi objekt ()); obj.sum (novi objekt (), novi objekt [] {novi objekt ()});

Očito je da će se prvi poziv vezati za zbroj (objekt, objekt) a drugi da zbroj (Objekt, Objekt []). Da bismo prisilili Java da drugu metodu pozove s dva objekta, moramo je umotati u niz kao u trećem pozivu.

Posljednje što ovdje treba primijetiti jest da će se izjašnjavanje sljedeće metode sukobiti s verzijom vararg:

zbroj javnog broja (pojam objekta1, objekt [] pojam2) {// ...}

6. Zaključak

U ovom uputstvu saznali smo da se potpisi metode sastoje od imena i popisa vrsta parametara. Modifikatori, vrsta povratka, imena parametara i popis iznimki ne mogu razlikovati preopterećene metode i, prema tome, nisu dio potpisa.

Također smo pogledali kako brisanje tipova i varargs skrivaju učinkoviti potpis metode i kako možemo nadjačati Java-ovo statično vezanje.

Kao i obično, svi uzorci koda prikazani u ovom članku dostupni su na GitHubu.