Kas porą mėnesių gaunu panikos ar sumišimo el. Laišką iš „JavaBeans“ neofito, kuris bando sukurti „JavaBean“, kuriame yra Vaizdas
ir kas negali suprasti, kodėl „BeanBox“ neapkraus pupelės. Problema ta java.awt.Vaizdas
nėra Serijinis
, todėl nėra nieko, kuriame yra a java.awt.Vaizdas
, bent jau be pasirinktinio serijavimo.
Aš pats praleidau begales valandų dėdamas println ()
teiginius į „BeanBox“ kodą, tada jį vėl sukompiliuodamas, bandydamas išsiaiškinti, kodėl mano pupelės nebus įkeltos. Kartais tai atsitinka dėl kažkokio paprasto, kvailo dalyko - pavyzdžiui, pamiršti apibrėžti nulinio argumento konstruktorių ar net klasę, kaip visuomenės
. Kitais atvejais tai pasirodo kažkas neaiškesnio.
Dingusio pupelės atvejis
Nors reikalavimai rašyti „Java“ klasę kaip „JavaBean“ yra paprasti ir aiškūs, yra keletas paslėptų pasekmių, kurių daugelis pupelių kūrimo įrankių netaiko. Šie mažai gotchas gali lengvai suvalgyti popietę, kai ieškai kodo, ieškodamas priežasties, kodėl statybininko įrankis neranda tavo pupelės. Jei pasiseks, gausite iššokantįjį dialogo langą su kriptiniu klaidos pranešimu - kažkas panašaus į „„NoSuchMethodException“ pateko į „FoolTool“ savikontrolę
"Jei jums nepasisekė,„ JavaBean “, į kurį įpylėte tiek prakaito, atsisakys būti rodomas jūsų kūrėjo įrankyje, o jūs praleisite popietę repetuodami žodyną, kurį jūsų mama taip stengėsi išgydyti.„ BeanBox “ jau seniai buvo šiurkštus pažeidėjas šiuo klausimu, ir, nors jis tobulėjo, jis vis tiek sumažins savybes ir net visas pupeles, nepateikdamas kūrėjui vienintelio supratimo, kodėl.
Šį mėnesį išvesiu jus iš „dingusių pupelių žemės“ pristatydama naują įrankį, pavadintą keista, PupelėLint
, kuriame analizuojamos stiklainių failų klasės, ieškoma galimų problemų, dėl kurių klasės būtų netinkamos naudoti kaip pupelės. Nors šis įrankis neapima visų įmanomų pupelių problemų, jis nustato keletą pagrindinių problemų, dėl kurių pupelės gali būti iškraunamos.
Tam, kad suprastum kaip PupelėLint
veikia savo magiją, šį ir kitą mėnesį mes gilinsimės į keletą mažiau žinomų standartinės „Java“ API kampų:
Mes sukursime pasirinktį klasės krautuvas, kuris iš „jar“ failo įkelia naujas „Java“ klases
Mes naudosime atspindys mechanizmas, leidžiantis „Java“ programoms analizuoti „Java“ klases, kad būtų galima nustatyti, kas yra mūsų klasės failuose
- Mes naudosime
Introspektorius
parengti visų klasės pupelių savybių ataskaitą bet kuriai stiklainio failo klasei, kuri išlaikė visus testus (ir todėl yra potenciali pupelė)
Kol baigsime, turėsite naudingą įrankį pupelių derinimui, geriau suprasite pupelių reikalavimus ir tuo pačiu metu sužinosite apie kai kurias naujas „Java“ funkcijas.
Pupelių pagrindai
Kad klasės failas būtų „JavaBean“, yra du paprasti reikalavimai:
Klasėje turi būti viešasis konstruktorius be jokių argumentų (a nulio arg konstruktorius)
- Klasė turi įdiegti tuščią žymos sąsają
java.io.Serializuojama
Viskas. Laikykitės šių dviejų paprastų taisyklių ir jūsų klasė bus „JavaBean“. Taigi paprasčiausias „JavaBean“ atrodo maždaug taip:
importuoti java.io. *; viešoji klasė „TinyBean“ įgyvendina „Serializable“ {public TinyBean () {}}
Žinoma, aukščiau paminėtas pupelis nėra naudingas daugeliui, bet tada mes nepadėjome daug darbo. Tiesiog bandyti tokio pagrindinio komponento rašymas kitoje komponentų sistemoje. (Ir nesąžininga naudojant „burtininkus“ ar kitus kodų generatorius kuriant įvyniojimo klases ar numatytuosius diegimus. Tai nėra teisingas „JavaBeans“ elegancijos ir kitos technologijos palyginimas.)
„TinyBean“
klasė neturi savybių (išskyrus, galbūt, „vardą“), jokių įvykių ir metodų. Deja, vis tiek lengva netyčia sukurti klases, kurios, atrodo, laikosi taisyklių, tačiau tinkamai neveikia „JavaBeans“ talpykloje, tokioje kaip „BeanBox“ ar jūsų mėgstamiausia IDE (integruota kūrimo aplinka).
Pavyzdžiui, „BeanBox“ neįkrautų mūsų „TinyBean“
aukščiau, jei pamiršome įtraukti raktinį žodį visuomenės
pagal klasės apibrėžimą. javac
sukurs klasės failą, tačiau „BeanBox“ atsisakys jį įkelti ir (vis tiek iki šiol) nenurodys, kodėl atsisakys. Norėdamas suteikti „Sun“ „Java“ žmonėms kreditą, „BeanBox“ dabar paprastai nurodo priežastį, kodėl pupelė neįkeliama, arba priežastį, kodėl ypatybė nerodoma nuosavybės lape ir pan. Argi nebūtų malonu, jei turėtume įrankį, kad patikrintume kuo daugiau dalykų apie tokias klases ir perspėtume mus apie tuos, kurie gali sukelti problemų naudojant „JavaBeans“ aplinką? Tai yra tikslas PupelėLint
: padėti jums, kaip „JavaBeans“ programuotojui, išanalizuoti pupeles jų indelių failuose, ieškant galimų problemų, kad galėtumėte jas išspręsti prieš susidurdami bandymo procese arba - dar blogiau - lauke.
Galimos pupelių problemos
Kurdamas „JavaBeans“ šiai skiltiai, tikriausiai padariau daugiausiai klaidų, kurias galima padaryti rašant „JavaBean“. Tam tikra prasme tylus „BeanBox“ pobūdis privertė mane sužinoti daugiau apie pupeles - ir apie „Java“, nei būčiau turėjęs kitaip. Vis dėlto dauguma „JavaBeans“ kūrėjų norėtų paprasčiausiai gaminti veikiančius „JavaBeans“, kurie veiktų tinkamai ir išsaugotų „augimo patirtį“ asmeniniam gyvenimui. Aš surinkau sąrašą galimų klasės failo problemų, kurios gali sugadinti „JavaBean“. Šios problemos kyla pupelių pakrovimo į konteinerį metu arba naudojant pupeles programoje. Serializuojant lengva praleisti išsamią informaciją, todėl ypatingą dėmesį skiriame serializavimo reikalavimams.
Čia yra keletas dažniausiai pasitaikančių problemų, kurios nesukelia kompiliavimo laiko klaidų, tačiau gali sukelti ir klasės failą būti „JavaBean“ arba netinkamai veikti, kai bus įkelta į konteinerį:
Klasėje nėra nulinio argumento konstruktoriaus. Tai paprasčiausiai pažeidžia pirmąjį aukščiau išvardytą reikalavimą ir yra klaida, su kuria dažnai nesusiduria ne pradedantieji.
Klasė neįgyvendinama
Serijinis
. Tai yra antrojo aukščiau išvardyto reikalavimo pažeidimas ir jį lengva pastebėti. Klasė gali reikalavimas įgyvendintiSerijinis
ir vis dėlto nesilaikykite sutarties. Kai kuriais atvejais mes galime tai aptikti automatiškai.Pati klasė nėra deklaruojama
visuomenės
.Klasės dėl kažkokių priežasčių nepavyksta įkelti. Klasės kartais įkelia išimtis. Dažnai taip yra todėl, kad kitų klasių, nuo kurių jie priklauso, nėra
„ClassLoader“
objektas, naudojamas įkelti klasę. Šiame straipsnyje parašysime pasirinktinį klasės krautuvą (žr. Toliau).Klasė yra abstrakti. Nors teoriškai komponentų klasė gali būti abstrakti, faktinis „JavaBean“ vykdomasis egzempliorius visada yra kažkokios konkrečios (tai yra ne abstrakčios) klasės egzempliorius. Abstrakčių klasių negalima apibrėžti pagal apibrėžimą, todėl abstrakčios klasės nelaikysime pupelėmis.
- Klasė
įgyvendina Serializable
, tačiau joje arba vienoje iš pagrindinių klasių yra nenerializuojamų laukų. Numatytasis „Java“ serializavimo mechanizmo dizainas leidžia klasę apibrėžti kaipįgyvendina Serializable
, bet leidžia jai nepavykti, kai iš tikrųjų bandoma serializuoti. MūsųPupelėLint
klasė užtikrina, kad visi tinkami a. laukaiSerijinis
klasės iš tikrųjų yraSerijinis
.
Klasė, kuriai nepavyksta išspręsti nė vienos iš aukščiau išvardytų problemų, gali būti visiškai tikra, kad ji tinkamai neveikia kaip „JavaBean“, net jei tenkinami du iš pradžių nurodyti pupelių reikalavimai. Kiekvienai iš šių problemų nustatysime testą, kuris aptiks konkrečią problemą ir praneša apie ją. Viduje konors PupelėLint
klasė, bet kuri stiklainio faile esanti failas yra analizuojamas daro visi šie bandymai yra tada savistaba (analizuojama naudojant klasę java.pupos.Tyrėjas
), kad būtų parengta pupelių atributų ataskaita (ypatybės, įvykių rinkiniai, pritaikymas ir pan.). java.pupos.Tyrėjas
yra klasė paketas java.pupos
kuri naudoja „Java 1.1“ atspindėjimo mechanizmą, kad surastų (arba sukurtų) a java.beans.BeanInfo
„JavaBean“ objektas. Apsvarstysime ir apžiūrėsime kitą mėnesį.
Dabar pažvelkime į šaltinio kodą PupelėLint
sužinoti, kaip analizuoti galimas pupelių klases.
Pristatome „BeanLint“
„Senais gerais laikais“ (tai paprastai reiškia „tada, kai dar maniau, kad viską žinau“) „C“ programuotojai „Unix“ operacinėje sistemoje naudos programą, vadinamą pūkelis
ieškoti galimų vykdymo trukmės problemų savo C programose. Gerbdamas šią garbingą ir naudingą priemonę, aš pašaukiau savo kuklią pupelių analizės klasę PupelėLint
.
Užuot pateikę visą šaltinio kodą viename didžiuliame, nesuvirškinamame gabalėlyje, mes jį nagrinėsime po vieną gabalą, ir aš kelyje paaiškinsiu įvairias idiomas apie tai, kaip „Java“ tvarko klasės failus. Iki to laiko mes parašysime klasių krautuvą, naudosime garbingą skaičių klasių java.lang.reflect
ir įgijo linktelėjusią pažintį su klase java.pupos.Tyrėjas
. Pirmiausia pažvelkime PupelėLint
kad sužinotume, ką jis daro, ir tada mes įsigilinsime į jo įgyvendinimo detales.
Blogos pupelės
Šiame skyriuje pamatysite keletą klasės failų su įvairiomis problemomis, kurių problema nurodyta po kodu. Mes sukursime jar failą, kuriame bus šios klasės, ir pamatysime ką PupelėLint
daro su jais.
importuoti java.io. *;
viešoji klasė w įgyvendina „Serializable“ {w () {}}
Problema:
Nulio argumentų konstruktorius ne
visuomenės
viešoji klasė x {public x () {}}
Problema:
Ne
Serijinis.
importuoti java.io. *;
„y“ viešoji klasė įgyvendina „Serializable“ {public y (String y_) {}}
Problema:
Nėra nulinio argumento konstruktoriaus.
importuoti java.io. *;
z klasės įrankiai „Serializable“ {public z () {}}
Problema:
Klasė nėra vieša.
importuoti java.io. *; importuoti java.awt. *;
u0 klasė įgyvendina Serializuojamą {privatų vaizdą i; viešasis u0 () {}}
u klasė u pratęsia u0 įrankius Serializuojama {public u () {}}
Problema:
Sudėtyje nenurodomas objektas ar nuoroda.
importuoti java.io. *;
viešoji klasė v pratęsia java.awt.Button įgyvendina Serializable {public v () {} public v (String s) {super (s); }}
Problema:
Niekas - turėtų gerai veikti!
Kiekviena iš šių trokštančių pupelių, išskyrus paskutinę, turi galimų problemų. Paskutinis yra ne tik pupelė, bet ir veikia kaip viena. Sudarę visas šias klases, mes sukuriame tokį failą:
$ jar cvf BadBeans.jar * .class pridėjimas: u.class (in = 288) (out = 218) (defliacija 24%) pridedant: u0.class (in = 727) (out = 392) (defluota 46% pridėjus: w.class (in = 302) (out = 229) (defliacija 24%) pridedant: x.class (in = 274) (out = 206) (deflated 24%) pridedant: y.class (in = 362) (out = 257) (ištuštinta 29%) pridedant: z.klasė (in = 302) (out = 228) (defluota 24%) pridedant: v.class (in = 436) (out = 285) (deflatuota 34%)
Mes neįtrauksime manifesto failo (kuris yra failas stiklainio faile, kuris apibūdina stiklainio failo turinį - žr. Žemiau „Stiklo atidarymas“) į stiklainio failą, nes PupelėLint
nenagrinėja manifestų failų. Analizuoti manifesto failą ir palyginti jį su indelio turiniu būtų įdomus pratimas, jei norite ką pratęsti PupelėLint
gali padaryti.
Pabėgiokime PupelėLint
ant stiklainio failo ir pažiūrėkite, kas vyksta:
=== Klasės u0 analizavimas === u0 klasė nėra „JavaBean“, nes: klasė nėra vieša
=== Klasės z analizavimas === z klasė nėra „JavaBean“, nes: klasė nėra vieša
=== Y klasės analizavimas === y klasė nėra „JavaBean“, nes: joje nėra nulinio argumento konstruktoriaus
=== „x“ klasės analizė === „x“ klasė nėra „JavaBean“, nes: klasė nėra serijinė
=== Klasės w analizė === klasė w nėra „JavaBean“, nes: jo nulinio argumento konstruktorius nėra viešas
=== Analizuojama v klasė === Pastaba: java.awt.Button apibrėžia pasirinktinį serijavimą Pastaba: java.awt.Component apibrėžia pasirinktinį serializavimą v perduoda visus „JavaBean“ testus
Įsižiūrėjimo ataskaita -------------------- Klasė: v Tinkintuvo klasė: nėra
Ypatybės: loginė reikšmė įgalinta {isEnabled, setEnabled} (... dar daug ypatybių)
Įvykių rinkiniai: java.awt.event.MouseListener mouse (... dar daug įvykių rinkinių)
Metodai: viešoji loginė java.awt.Component.isVisible () (... daug, daugelis daugiau metodų - sheesh!)
=== V klasės pabaiga ===
=== „u“ klasės analizavimas === „u“ klasė nėra „JavaBean“, nes: šie klasės laukai nėra serijiniai: klasė java.awt. I vaizdas (apibrėžtas u0) === U klasės pabaiga ===
Išvestis buvo šiek tiek sutrumpinta, nes įvykių rinkinių ir metodų sąrašas yra labai ilgas, mūsų diskusijai čia daug neprideda. Galite pamatyti visą išvestį faile output.html, jei norite idėjos apie daiktų kiekį PupelėLint
išleidžia.
Pastebėti, kad PupelėLint
teisingai nustatė blogos klasės failų problemas:
u0 klasė nėra „JavaBean“, nes: klasė nėra vieša klasė z nėra „JavaBean“, nes: klasė nėra vieša, y klasė nėra „JavaBean“, nes: ji neturi nulinio argumento konstruktoriaus klasė x nėra „JavaBean“, nes: klasė nėra Serializuojama klasė w nėra „JavaBean“, nes: jos nulinio argumento konstruktorius nėra viešas. „u“ nėra „JavaBean“, nes: šie klasės laukai nėra Serializuojami: klasė java.awt. Vaizdas i (apibrėžtas u0)