Upišite Obriši u Java Objašnjeno

1. Pregled

U ovom ćemo kratkom članku razgovarati o osnovama važnog mehanizma u Java generiku poznatom kao brisanje tipova.

2. Što je brisanje tipa?

Brisanje tipa može se objasniti kao postupak nametanja ograničenja tipa samo u vrijeme kompajliranja i odbacivanja podataka o tipu elementa tijekom izvođenja.

Na primjer:

javna statička logička vrijednost sadržiElement (E [] elementi, E element) {for (E e: elements) {if (e.equals (element)) {return true; }} return false; }

Prevoditelj zamjenjuje nevezani tip E sa stvarnom vrstom Objekt:

javna statička logička vrijednost sadržiElement (Object [] elementi, Object element) {for (Object e: elements) {if (e.equals (element)) {return true; }} return false; }

Stoga kompajler osigurava sigurnost tipa našeg koda i sprječava runtime greške.

3. Vrste brisanja tipova

Brisanje tipa može se dogoditi na razini klase (ili varijable) i metode.

3.1. Brisanje tipa klase

Na razini klase, kompajler odbacuje parametre tipa na klasi i zamjenjuje ih svojim prvim vezanim, ili Objekt ako je parametar tipa nevezan.

Provedimo a Stog pomoću niza:

javna klasa Stack {private E [] stackContent; javni stog (int kapacitet) {this.stackContent = (E []) novi objekt [kapacitet]; } javni void push (E podaci) {// ..} public E pop () {// ..}}

Nakon kompilacije, prevodilac zamjenjuje nevezani parametar tipa E s Objekt:

javna klasa Stack {private Object [] stackContent; javni stog (int kapacitet) {this.stackContent = (Object []) novi objekt [kapacitet]; } javni void push (podaci o objektu) {// ..} public Object pop () {// ..}}

U slučaju kada parametar tipa E je vezan:

javni razred BoundStack {private E [] stackContent; javni BoundStack (int kapacitet) {this.stackContent = (E []) novi objekt [kapacitet]; } javni void push (E podaci) {// ..} public E pop () {// ..}}

Prevoditelj će zamijeniti parametar vezanog tipa E s prvom vezanom klasom, Usporedive u ovom slučaju:

javna klasa BoundStack {private Comparable [] stackContent; javni BoundStack (int kapacitet) {this.stackContent = (Usporediv []) novi objekt [kapacitet]; } javni void push (usporedivi podaci) {// ..} javni usporedivi pop () {// ..}}

3.2. Brisanje tipa metode

Za brisanje tipa na razini metode, parametar tipa metode se ne pohranjuje, već se pretvara u roditeljski tip Objekt ako je nevezan ili je prva vezana klasa kad je vezan.

Razmotrimo metodu za prikaz sadržaja bilo kojeg datog niza:

javna statička praznina printArray (E [] niz) {for (E element: array) {System.out.printf ("% s", element); }}

Nakon kompilacije, kompajler zamjenjuje parametar tipa E s Objekt:

javna statička praznina printArray (Object [] array) {for (Element objekta: array) {System.out.printf ("% s", element); }}

Za parametar tipa vezane metode:

javna statika  void printArray (E [] array) {for (E element: array) {System.out.printf ("% s", element); }}

Imat ćemo parametar tipa E izbrisana i zamijenjena sa Usporedivo:

javna statička praznina printArray (usporediv [] niz) {za (usporedivi element: niz) {System.out.printf ("% s", element); }}

4. Rubni slučajevi

Negdje tijekom postupka brisanja tipa, kompajler stvara sintetsku metodu za razlikovanje sličnih metoda. Oni mogu potjecati iz potpisa metode koji proširuju istu prvu povezanu klasu.

Stvorimo novu klasu koja proširuje našu prethodnu implementaciju Stog. Imajte na umu da se ovo odnosi na Stog razred u kojem smo stvorili odjeljak 3.1, i ne java.util.Stack.

javna klasa IntegerStack proširuje Stack {javni IntegerStack (int kapacitet) {super (kapacitet); } javni void push (Integer value) {super.push (value); }}

Sada pogledajmo sljedeći kod:

IntegerStack integerStack = novi IntegerStack (5); Stog stoga = integerStack; stack.push ("Zdravo"); Cjelobrojni podaci = integerStack.pop ();

Nakon brisanja tipa, imamo:

IntegerStack integerStack = novi IntegerStack (5); Stog stoga = (IntegerStack) integerStack; stack.push ("Zdravo"); Cijeli podaci = (Niz) integerStack.pop ();

Primijetite kako možemo pritisnuti a String na IntegerStack - jer IntegerStack naslijeđena push (objekt) iz roditeljskog razreda Stog. To je, naravno, netočno - jer bi od tada trebao biti cijeli broj integerStack je Stog tip.

Stoga, nije iznenađujuće, pokušaj pop a Niz i dodijeliti Cijeli broj uzrokuje a ClassCastException iz gipsa umetnutog tijekom gurnuti od strane sastavljača.

4.1. Mostovne metode

Da bi riješio gornji slučaj ruba, kompajler ponekad kreira metodu premošćivanja. Ovo je sintetička metoda koju je kreirao Java prevodilac tijekom sastavljanja klase ili sučelja koja proširuje parametarsku klasu ili implementira parametrizirano sučelje gdje se potpisi metode mogu malo razlikovati ili dvosmisleno.

U našem primjeru iznad, Java kompajler čuva polimorfizam generičkih tipova nakon brisanja osiguravajući da ne postoji neusklađenost potpisa između metoda IntegerStack‘S push (Integer) metoda i Stog‘S push (objekt) metoda.

Stoga prevodilac ovdje stvara metodu premošćivanja:

javna klasa IntegerStack proširuje Stack {// metoda povezivanja generirana kompajlerom public void push (vrijednost objekta) {push ((Integer) vrijednost); } javni void push (Integer value) {super.push (value); }}

Slijedom toga, Stog razredu gurnuti metoda nakon brisanja tipa, delegira na izvornik gurnuti metoda IntegerStack razred.

5. Zaključak

U ovom uputstvu raspravljali smo o konceptu brisanja tipa s primjerima u varijablama i metodama parametara tipa.

Možete pročitati više o ovim konceptima:

  • Specifikacija jezika Java: brisanje tipa
  • Osnove Java generike

Kao i uvijek, izvorni kod koji prati ovaj članak dostupan je na GitHubu.