Programiranje

Java Nasvet 99: Avtomatizirajte ustvarjanje toString ()

Razvijalci, ki delajo na velikih projektih, pogosto ure in ure pišejo koristno toString metode. Tudi če vsak razred ne dobi svojega toString , bo vsak razred vsebnika podatkov. Dovoljenje vsakemu razvijalcu, da piše toString njegova pot lahko vodi v kaos; vsak razvijalec bo nedvomno pripravil edinstveno obliko. Posledično je uporaba izhoda med odpravljanjem napak težja, kot je potrebno, brez očitnih koristi. Zato bi se moral vsak projekt standardizirati v enem samem formatu za toString metode in nato avtomatizirajo njihovo ustvarjanje.

Avtomatizirajte v niz

Zdaj bom predstavil pripomoček, s katerim lahko storite prav to. To orodje samodejno ustvari navaden in zanesljiv

toString

metodo za določen razred, skoraj odpravi čas, porabljen za razvoj metode. Prav tako centralizira

toString ()

format. Če spremenite obliko, morate obnoviti datoteko

toString

metode; vendar je to še vedno veliko lažje kot ročno spreminjanje stotih ali tisočih razredov.

Tudi vzdrževanje ustvarjene kode je enostavno. Če v razrede dodate več atributov, boste morda morali vnesti spremembe v toString tudi metoda. Od generacije toString metode je avtomatizirana, za izvedbo sprememb morate le znova zagnati pripomoček v razredu. To je preprostejše in manj nagnjeno k napakam kot ročni pristop.

Koda

Ta članek ni namenjen razlagi API Reflection; naslednja koda predpostavlja, da vsaj razumete koncepte, ki stojijo za Reflection. Lahko obiščete

Viri

odsek za dokumentacijo Reflection API. Pripomoček je zapisan na naslednji način:

paket fareed.publications.utilities; uvoz java.lang.reflect. *; javni razred ToStringGenerator {public static void main (String [] args) {if (args.length == 0) {System.out.println ("Navedite ime razreda kot argument ukazne vrstice"); System.exit (0); } poskusite {Class targetClass = Class.forName (args [0]); if (! targetClass.isPrimitive () && targetClass! = String.class) {Polja polja [] = targetClass.getDeclaredFields (); Razred cSuper = targetClass.getSuperclass (); // Pridobivanje izhoda super razreda ("StringBuffer buffer = new StringBuffer (500);"); // Konstrukcija medpomnilnika if (cSuper! = Null && cSuper! = Object.class) {output ("buffer.append (super.toString ());"); // toString ()} super razreda za (int j = 0; j <polja.dolžina; j ++) {output ("buffer.append (\" "+ polja [j] .getName () +" = \ "); "); // Dodaj ime polja if (polja [j] .getType (). IsPrimitive () || polja [j] .getType () == String.class) // Preveri, ali je izhod primitiven ali niz ("buffer.append ( to. "+ polja [j] .getName () +"); "); // Dodaj vrednost primitivnega polja else {/ * NI primitivno polje, zato to zahteva preverjanje vrednosti NULL za agregirani objekt * / output ("if (this." + Polja [j] .getName () + "! = null)"); output ("buffer.append (this." + polja [j] .getName () + ".toString ());"); output ("else buffer.append (\" vrednost je null \ ");"); } // konec drugega} // konec izhoda zanke ("return buffer.toString ();"); }} catch (ClassNotFoundException e) {System.out.println ("Razred ni najden na poti do razreda"); System.exit (0); }} zasebni statični izhod iz praznine (podatki v nizu) {System.out.println (podatki); }} 

Izhodni kanal kode

Oblika kode je odvisna tudi od zahtev vašega orodja za projekt. Nekateri razvijalci imajo morda raje kodo v uporabniško določeni datoteki na disku. Drugi razvijalci so z

sistem.out

konzola, ki jim omogoča ročno kopiranje in vdelavo kode v dejansko datoteko. Te možnosti preprosto prepustim vam in uporabim najpreprostejšo metodo:

sistem.out

izjave.

Omejitve pristopa

Ta pristop imata dve pomembni omejitvi. Prvi je, da ne podpira predmetov, ki vsebujejo cikle. Če objekt A vsebuje sklic na objekt B, ki nato vsebuje sklic na objekt A, to orodje ne bo delovalo. Vendar bo ta primer za številne projekte redek.

Druga omejitev je, da dodajanje ali odštevanje spremenljivk člana zahteva regeneracijo toString metoda. Ker je to treba storiti z orodjem ali brez njega, to ni poseben problem za ta pristop.

Zaključek

V tem članku sem razložil majhen pripomoček za avtomatizacijo, ki lahko resnično izboljša produktivnost razvijalcev in igra majhno, a pomembno vlogo pri zmanjševanju celotnega časovnega okvira projekta.


Nasveti za nadaljnje ukrepe

Po objavi tega nasveta sem od bralcev prejel nekaj predlogov, kako izboljšati kodo. V nadaljevanju pojasnjujem, kako sem na podlagi teh predlogov in lastnih spoznanj posodobil pripomoček. Izvorno kodo za te izboljšave najdete v virih.

Izboljšanje št. 1, ki jo je predlagala Sangeeta Varma

V svoji prvotni kodi nisem obravnaval vrst matrike za objekt in primitivni podatkovni tip; nova koda zdaj obravnava podatke matrike. Vendar se koda povzpne samo do enorazsežnih nizov in ne bo delovala za večdimenzionalna polja. Splošne rešitve za to težavo nisem mogel najti, saj po mojem vedenju ni omejitev števila dimenzij za podatkovne vrste v Javi (edina omejitev je razpoložljivi pomnilnik). Pozdravljam vse povratne informacije, ki jih lahko ponudite za rešitev.

Izboljšanje št. 2, ki ga je predlagal Chris Sanscraint

Prvotno sem pripomoček predlagal za razvojni čas in ne za izvajalno okolje. Dovoljenje, da se pripomoček izvaja med izvajanjem, je lahko zelo priročen, vendar lahko traja še nekaj ciklov CPU. Vendar pa odmetavanje / odpravljanje napak (osnovna uporaba toString ()) se običajno izvaja v času razvoja in je izključen za proizvodno okolje. V nekaterih primerih ta izklop v proizvodnem okolju morda ne bo uporaben, saj se lahko uporabljajo nekateri projekti toString () za namene poslovne logike. Predlagam, da se odločite za vsak projekt posebej.

Pred razvojem tega pripomočka sem že imel v mislih to prilagodljivost med izvajanjem. Najprej sem razvil ločen delegirajoči razred, ki ga je kateri koli odjemalski razred uporabil za generiranje toString (). Razred ga je ustvaril z uporabo klica metode, kot je vrni ToStringGenerator.generateToString (to), kje to kaže na trenutni primerek odjemalskega razreda in stavek kode je zapisan v toString () izvajanje metode. Toda ta pristop ni uspel, ker API Reflection nima možnosti pridobivanja vrednosti za zasebne člane med izvajanjem. Torej je bil pouk uporaben samo za javne člane, česar pa nisem želel.

Potem pa je gospod Sanscraint poudaril, da ista koda API Reflection dobi vrednost zasebnih članov med izvajanjem, ko je koda napisana v metodi istega razreda klicatelja. Tako sem posodobil pripomoček, ki se bo uporabljal med izvajanjem, poleg tega pa še toString () metode nikoli ne bo treba posodobiti ali urediti za odštevanje ali dodajanje kakršnih koli atributov v ciljnem razredu.

Izboljšanje št. 3, ki ga predlaga Eric Ye

Prvotno sem uporabljal to predpono za dostop spremenljivk člana v ustvarjeni kodi, vendar je g. Ye poudaril, da se koda lahko uporablja tudi v statični metodi ali celo za izpis statičnih članov. Tako lahko posodobljena koda zdaj obravnava člane razreda in primerka. G. Ye je ugotovil tudi napako, ki je bila odpravljena v tej različici, zaradi katere je razred ustvarjal neuporabno kodo za razrede brez atributov.

Spremembe kode

Ko sem omogočil izvajanje pripomočka, me je razočaralo, da sem moral kopirati / prilepiti metode v vsak razred, kar je postalo težko, saj je bila nova koda sestavljena iz več metod.

Ena od rešitev bi bila ustvariti vmesnik / abstraktni osnovni razred, ki bi rešil vsaj problem podpisov metode, vendar bi bilo kopiranje / lepljenje še vedno potrebno. Rešitev abstraktnega osnovnega razreda bi tudi odjemalcu omejila izhajanje iz drugega razreda.

Notranji razred pa ima možnost dostopa do zasebnih članov nadrejenega razreda, tako da lahko koda odseva, ki se izvaja znotraj njegovih metod, dobi tudi zasebne vrednosti. Zato sem se odločil spremeniti pripomoček v notranji razred, ki ga je mogoče vstaviti v kateri koli nadrejeni odjemalski razred. Priskrbel sem tudi ToStringGeneratorExample.java, ki uporablja ToStringGenerator.java kot notranji razred za izvajanje toString () metoda.

Na koncu bi se rad zahvalil tistim, ki so dali svoje predloge za izboljšanje tega pristopa.

Syed Fareed Ahmad je programer, oblikovalec in arhitekt Java v Lahoreju v Pakistanu. Ukvarja se z razvojem rešitev za e-poslovanje na osnovi Java (Servlets, JSP in EJB), WebSphere in XML.

Preberite več o tej temi

  • Za nadaljnjo izvorno kodo

    //images.techhive.com/downloads/idge/imported/article/jvw/2000/08/jw-javatip99.zip

  • Dokumentacija za razmislek na spletnem mestu Sun

    //java.sun.com/products/jdk/1.1/docs/guide/reflection/index.html

  • Oglejte si vse prejšnje Java Nasveti in oddajte svojega

    //www.javaworld.com/javatips/jw-javatips.index.html

To zgodbo, "Java Tip 99: Automate toString () create", je prvotno objavil JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found