Programavimas

„BeanLint“: „JavaBeans“ trikčių šalinimo įrankis, 1 dalis

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:

  1. Klasėje turi būti viešasis konstruktorius be jokių argumentų (a nulio arg konstruktorius)

  2. 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 įgyvendinti Serijinisir 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. laukai Serijinis klasės iš tikrųjų yra Serijinis.

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.reflectir į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) 
$config[zx-auto] not found$config[zx-overlay] not found