Kas yra generinių vaistų ištrynimo Java sistemoje sąvoka?

Kas yra generinių vaistų ištrynimo Java sistemoje sąvoka?

115
24 нояб. Tushu rinkinys 24 lapkričio. 2008-11-24 10:20 '08, 10:20, 2008-11-24 10:20
@ 7 atsakymai

Iš esmės tai yra, kaip generiniai įrankiai „Java“ diegiami kompiliatoriaus sukčiavimu. Apibendrintas bendrinis kodas iš tikrųjų tiesiog naudoja java.> kur jūs kalbate apie T (arba kitą tipo parametrą) - ir yra keletas metaduomenų, kad kompiliatoriui būtų pranešta, kad jis tikrai yra bendro pobūdžio.

Kai kompiliuojate bet kurį kodą pagal bendrąjį tipą ar metodą, kompiliatorius kuria tai, ką iš tikrųjų reiškia (tai yra, kokio tipo argumentas yra skirtas T ), ir kompiliavimo metu jis patikrina, ar darote teisingą dalyką, bet emituotas kodas vėl tiesiog sako, kalbant apie java.> - kompiliatorius, jei reikia, generuoja papildomus įrašus. Paleidimo metu List<String> ir List<Date> yra lygiai tokie patys; kompiliatorius ištrino papildomą tipo informaciją.

Palyginkite tai, pvz., C #, kur informacija saugoma vykdymo metu, leidžiant kodui turėti tokias išraiškas, kaip tipo typeof(T) , kuris yra lygiavertis T.class išskyrus tai, kad pastaroji negalioja. (Yra papildomų skirtumų tarp .NET generatorių ir „Java“ generikų, pastaba.) Tipo trynimas yra daugelio „nelyginių“ įspėjimų / klaidų pranešimų šaltinis dirbant su „Java“ generiniais.

Kiti ištekliai:

24 нояб. Atsakymą pateikė Jon Skeet lapkričio 24 d 2008-11-24 10:25 '08, 10:25, 2008-11-24 10:25

Atkreipkite dėmesį į įdomią užduotį, kuria siekiama pamatyti, ką kompiliatorius atlieka, kai atlieka ištrynimą, todėl lengva suprasti visą koncepciją. Yra speciali vėliava, kurią galite perduoti kompiliatoriui, kad būtų galima išleisti java failus, kuriuose generuojami generiniai vaistai ir įterpti lapai. Pavyzdys:

 javac -XD-printflat -d output_dir SomeFile.java 

-printflat yra vėliava, perduodama kompiliatoriui, kuris generuoja failus. ( -XD dalis yra tai, kas pasakoja -XD perkelti į vykdomąjį indelį, kuris faktiškai surenka ne tik javac , bet ir išsiblaškęs ...) -d output_dir reikia, nes kompiliatoriui reikia tam tikros vietos nauji .java failai.

Tai, žinoma, yra daugiau nei tiesiog ištrinti; čia visi automatiniai dalykai, kuriuos kompiliatorius atlieka. Pavyzdžiui, pridedami numatytieji konstruktoriai, naujos foreach stiliaus kilpos išplėstos į įprastas kilpas ir pan. Malonu matyti mažus dalykus automatiškai.

31
05 июня '09 в 22:01 2009-06-05 22:01 atsakymą pateikė „ jigawot“ birželio 05 d. , 09:01 val. 2009-06-05 22:01

Norint užbaigti Johno Skito išsamų atsakymą, turite žinoti, kad reikia ištrinti suderinamumo su ankstesnėmis „Java“ versijomis poreikį.

Iš pradžių buvo pristatytas „EclipseCon 2007“ (nebėra), suderinamumas apėmė šiuos punktus:

  • Šaltinio suderinamumas (malonu turėti ...)
  • Dvejetainis suderinamumas (reikalingas!)
  • Migracijos suderinamumas
    • Esamos programos turi tęsti darbą.
    • Esamos bibliotekos turėtų turėti galimybę naudoti įprastas rūšis.
    • Tai turi būti!

Originalus atsakymas:

Todėl:

 new ArrayList<String>() => new ArrayList() 

Yra pasiūlymų dėl didesnio pataisymo . Reify "Apsvarstykite abstrakčią koncepciją kaip realią", kur kalbos konstrukcijos turėtų būti sąvokos, o ne tik sintaksinis cukrus.

Taip pat turiu paminėti „Java 6“ checkCollection metodą, kuris grąžina dinamiškai matomą nurodytos kolekcijos vaizdą. Bet koks bandymas įterpti neteisingo tipo elementą sukels neatidėliotiną ClassCastException .

Bendrasis mechanizmas kalba suteikia kompiliavimo laiko tipą (statinį), tačiau šį mechanizmą galima išvengti naudojant neišbandytus diskus .

Tai paprastai nėra problema, nes kompiliatorius įspėja apie visas tokias nepažymėtas operacijas.

Tačiau yra laiko, kai nepakanka statinio tipo tikrinimo, pavyzdžiui:

  • kai kolekcija perkeliama į trečiosios šalies biblioteką, ir būtina, kad bibliotekos kodas neiškraipytų kolekcijos, įterpdamas neteisingo tipo elementą.
  • programa neveikia su ClassCastException , nurodydama, kad neteisingai parinktas elementas buvo patalpintas į parametrų rinkinį. Deja, išimtis gali atsirasti bet kuriuo metu po to, kai įterpiamas klaidingas elementas, todėl paprastai jis pateikia mažai informacijos apie tikrąjį problemos šaltinį arba jo visai nėra.

Atnaujinta 2012 m. Liepos mėn., Beveik po ketverių metų:

Dabar (2012) išsamiai aprašyta skyriuje API suderinamumo taisyklės (parašo testas) "

„Java“ programavimo kalba įgyvendina generinius vaistus naudojant ištrynimą, o tai užtikrina, kad paliktos ir bendrosios versijos paprastai generuoja vienodas klasės rinkmenas, išskyrus tam tikrą papildomą informaciją. Dvejetainis suderinamumas nėra sugadintas, nes galima pakeisti pasenusį klasės failą į bendrą klasės failą nekeičiant ar nekompiliuojant bet kurio kliento kodo.

Siekiant palengvinti sąveiką su ne lygiaverčiu palikimu, taip pat galima naudoti parametro tipo ištrynimą kaip tipą. Šis tipas vadinamas neapdorotu tipu ( Java 3 / 4.8 kalbos specifikacija ). Šaltinio tipo skiriamoji geba taip pat suteikia grįžtamojo suderinamumo su pirminiu kodu.

Atitinkamai, šios java.util.Iterator klasės versijos yra dvejetainiai ir iš pradžių suderinami kodai:

 Class java.util.Iterator as it is defined in Java SE version 1.4: public interface Iterator { boolean hasNext(); Object next(); void remove(); } Class java.util.Iterator as it is defined in Java SE version 5.0: public interface Iterator<E> { boolean hasNext(); E next(); void remove(); } 
23
24 нояб. Atsakymą pateikė VonC 24 nov. 2008-11-24 10:38 '08, 10:38, 2008-11-24 10:38

Ištrynimas pažodžiui reiškia, kad šaltinio kode esanti tipo informacija pašalinama iš surinkto baito kodo. Apsvarstykime šį kodą.

 import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class GenericsErasure { public static void main(String args[]) { List<String> list = new ArrayList<String>(); list.add("Hello"); Iterator<String> iter = list.iterator(); while(iter.hasNext()) { String s = iter.next(); System.out.println(s); } } } 

Jei kompiliuojate šį kodą ir tuomet jį suformuosite su „Java“ decompileriu, gausite kažką panašaus. Atkreipkite dėmesį, kad dekompiliuotas kodas neturi tipo informacijos, esančios šaltinio kode, pėdsakų.

 import java.io.PrintStream; import java.util.*; public class GenericsErasure { public GenericsErasure() { } public static void main(String args[]) { List list = new ArrayList(); list.add("Hello"); String s; for(Iterator iter = list.iterator(); iter.hasNext(); System.out.println(s)) s = (String)iter.next(); } } 
18
13 дек. atsakymas pateikiamas 13 d. 2011-12-13 12:32 '11, 12:32, 2011-12-13 12:32

Be jau pridėto John Skit atsakymo ...

Buvo paminėta, kad generinių vaistų diegimas ištrinant sukelia tam tikrus erzinančius suvaržymus (pavyzdžiui, nėra new T[42] ). Taip pat buvo paminėta, kad pagrindinė priežastis yra atgalinis suderinamumas baitekode. Tai taip pat (daugiausia) tiesa. Sukurtas baitų kodas 1.5 tikslai šiek tiek skiriasi nuo paprasto nepageidaujamo liejimo tikslo 1.4. Techniniu požiūriu, netgi įmanoma (per didžiulį užkliuvimą) gauti prieigą prie universaliojo tipo atvejų vykdymo metu, įrodydamas, kad ten yra kažkas į šikšnosparnio kodą.

Įdomesnis dalykas (kuris nebuvo iškeltas) yra tai, kad bendrų įrankių, naudojant ištrynimą, įgyvendinimas siūlo daug lankstumo aukšto lygio sistemoje. Geras pavyzdys yra Scala JVM ir CLR įgyvendinimas. JVM galite tiesiogiai įgyvendinti aukštesnius vaizdus, ​​nes pats JVM neriboja bendrų tipų apribojimų (kadangi šie „tipai“ iš tikrųjų nėra). Tai prieštarauja CLR, kuris turi žinių apie parametrų vykdymo laiką. Dėl šios priežasties CLR turi turėti tam tikrą generinių vaistų vartojimo koncepciją, panaikindama bandymus išplėsti sistemą nenumatytomis taisyklėmis. Kaip rezultatas, „Scala“ aukštesni tipai CLR yra įgyvendinami naudojant keistą ištrynimo formą, sukurtą pačiame kompiliatoriuje, todėl jie nėra visiškai suderinami su įprastais .NET generiniais.

Ištrynimas gali būti nepatogu, kai norėsite atlikti neklaužada dalykų vykdymo metu, tačiau kompiliatorių autoriams jis suteikia maksimalų lankstumą. Manau, dalis, kodėl netrukus netrukus bus išnykta.

7
24 нояб. Daniel Spiewak atsakymas lapkričio 24 d 2008-11-24 11:29 '08, 11:29, 2008-11-24 11:29

Kaip tai suprantu (būdamas .NET vaikinu), JVM neturi bendrųjų sąvokų, todėl kompiliatorius pakeičia objekto tipo parametrus ir atlieka visą jūsų pasirinkimą.

Tai reiškia, kad „Java“ generiniai vaistai yra tik sintaksinis cukrus, ir nesiūlo jokio našumo pagerėjimo vertybių tipams, kuriems reikalingas bokso / išpakavimas.

5
24 нояб. Atsakymą pateikė Andrew Kennan lapkričio 24 d. 2008-11-24 10:25 '08, 10:25, 2008-11-24 10:25

Versija java 1.5 pristato bendrą programavimą
Pirmiausia, kas yra paplitusi java?
Bendras programavimas yra saugaus tipo objektas. Prieš rinkdami bendrą rinkinį, galime saugoti bet kokį objektą. ir po kartos turime saugoti tam tikro tipo duomenis.

Kokie yra „Generic“ privalumai?
Pagrindiniai bendro pobūdžio privalumai yra tai, kad liejimas pagal tipą nereikalingas, o taip pat ir išminčių tipo bei „Generic“ tikrina kompiliavimo laiką. ir bendroji bendroji sintaksė yra ClassOrInterface, čia tipas yra signalas, kurį ši klasė gali nustatyti klasei, kai ji sukūrė pavyzdį

Pavyzdys. GenericClassDemo

genericclassDemo = new GenericClassDemo (Employee.java)

-3
30 июля '15 в 23:35 2015-07-30 23:35 atsakymą pateikė JegsVala liepos 15 d. 15 val. 23:35 2015-07-30 23:35

Kiti klausimai apie „ žymų arba „ Klauskite“