Izstrādātāji, kas strādā pie lieliem projektiem, bieži pavada stundas, rakstot noderīgus toString
metodes. Pat ja katra klase neiegūst savu toString
metodi, katra datu konteineru klase būs. Ļaujot katram izstrādātājam rakstīt toString
viņa paša ceļš var izraisīt haosu; katrs izstrādātājs neapšaubāmi nāks klajā ar unikālu formātu. Tā rezultātā izejas izmantošana atkļūdošanas laikā kļūst sarežģītāka nekā nepieciešams bez acīmredzama ieguvuma. Tādēļ katram projektam būtu jāstandartizē vienots formāts toString
metodes un pēc tam automatizēt to izveidi.
Automatizējiet toString
Tagad es parādīšu lietderību, ar kuru jūs varat to izdarīt. Šis rīks automātiski ģenerē regulāru un stabilu
toString
metodi noteiktai klasei, gandrīz izslēdzot laiku, kas pavadīts metodes izstrādei. Tas arī centralizē
toString ()
formātā. Ja maināt formātu, jums ir jāatjauno
toString
metodes; tomēr tas joprojām ir daudz vieglāk nekā manuāli mainīt simtiem vai tūkstošiem klašu.
Arī ģenerētā koda uzturēšana ir vienkārša. Ja klasēs pievienojat vairāk atribūtu, jums, iespējams, būs jāveic izmaiņas toString
metode arī. Kopš toString
metodes ir automatizētas, lai veiktu izmaiņas, vēlreiz palaidiet tikai klases lietderību. Tas ir vienkāršāk un mazāk pakļauts kļūdām nekā manuālā pieeja.
Kods
Šis raksts nav paredzēts, lai izskaidrotu Reflection API; Šis kods pieņem, ka jums ir vismaz izpratne par pārdomām. Jūs varat apmeklēt
Resursi
sadaļa Reflection API dokumentācijai. Lietderība ir rakstīta šādi:
pakete fareed.publications.utilities; importēt java.lang.reflect. *; public class ToStringGenerator {public static void main (String [] args) {if (args.length == 0) {System.out.println ("Norādiet klases nosaukumu kā komandrindas argumentu"); System.exit (0); } mēģiniet {Class targetClass = Class.forName (argumenti [0]); if (! targetClass.isPrimitive () && targetClass! = String.class) {Lauka lauki [] = targetClass.getDeclaredFields (); Klase cSuper = targetClass.getSuperclass (); // Izgūst superklases izvadi ("StringBuffer buferis = jauns StringBuffer (500);"); // Bufera konstrukcija if (cSuper! = Null && cSuper! = Object.class) {output ("buffer.append (super.toString ());"); // Super klases toString ()} (int j = 0; j <lauki.length; j ++) {izeja ("buffer.append (\" "+ lauki [j] .getName () +" = \ "); "); // Pievienojiet lauka nosaukumu if (lauki [j] .getType (). IsPrimitive () || lauki [j] .getType () == String.class) // Pārbaudiet, vai ir primitīva vai virknes izeja ("buffer.append ( šo. "+ lauki [j] .getName () +"); "); // Pievienojiet primitīvā lauka vērtību else {/ * Tas NAV primitīvs lauks, tāpēc tas prasa pārbaudīt NULL vērtību apkopotajam objektam * / output ("if (this." + Lauki [j] .getName () + "! = null)"); izeja ("buffer.append (this." + lauki [j] .getName () + ".toString ());"); izeja ("else buffer.append (\" vērtība ir nulle \ ");"); } // beigas cits} // cilpas izvades beigas ("return buffer.toString ();"); }} catch (ClassNotFoundException e) {System.out.println ("Klase nav atrodama klases ceļā"); System.exit (0); }} privāta statiska tukšuma izvade (virknes dati) {System.out.println (dati); }}
Koda izvades kanāls
Koda formāts ir atkarīgs arī no projekta rīka prasībām. Daži izstrādātāji var izvēlēties, lai kods diskā būtu lietotāja definētā failā. Citi izstrādātāji ir apmierināti ar
system.out
konsole, kas ļauj viņiem manuāli kopēt un iegult kodu faktiskajā failā. Es vienkārši atstāju šīs iespējas jums un izmantoju vienkāršāko metodi:
system.out
paziņojumi.
Pieejas ierobežojumi
Šai pieejai ir divi svarīgi ierobežojumi. Pirmais ir tas, ka tas neatbalsta objektus, kas satur ciklus. Ja objektā A ir atsauce uz objektu B, kurā pēc tam ir atsauce uz objektu A, šis rīks nedarbosies. Tomēr šāds gadījums daudziem projektiem būs reti.
Otrais ierobežojums ir tāds, ka dalībnieku mainīgo pievienošanai vai atņemšanai ir nepieciešama toString
metodi. Tā kā tas jādara ar rīku vai bez tā, tā nav šai pieejai raksturīga problēma.
Secinājums
Šajā rakstā es izskaidroju nelielu automatizācijas lietderību, kas patiešām var uzlabot izstrādātāju produktivitāti un spēlēt nelielu, bet svarīgu lomu kopējā projekta laika grafika samazināšanā.
Turpmākie padomi
Pēc šī padoma publicēšanas es saņēmu dažus lasītāju ieteikumus, kā uzlabot kodu. Šajā turpinājumā es paskaidroju, kā esmu atjauninājis lietderību, pamatojoties uz šiem ieteikumiem un saviem ieskatiem. Šo uzlabojumu avota kodu varat atrast vietnē Resursi.
1. uzlabojums, ieteica Sangeeta Varma
Sākotnējā kodā es neapstrādāju objekta un primitīvo datu veida masīvu tipus; jaunais kods tagad apstrādā masīva datus. Tomēr kods iet tikai uz vienas dimensijas masīviem un nedarbosies vairāku dimensiju masīvos. Man nav izdevies piedāvāt vispārēju šīs problēmas risinājumu, jo, cik man zināms, Java datu tipu izmēru skaitam nav ierobežojumu (vienīgais ierobežojums ir pieejamā atmiņa). Es atzinīgi vērtēju visas atsauksmes, kuras varat piedāvāt risinājumam.
Uzlabojums Nr. 2, ko ierosināja Kriss Sanskreints
Sākotnēji es ierosināju lietderību izstrādes laikam, nevis izpildlaika videi. Ļaut lietderībai darboties izpildlaikā var būt ļoti ērti, taču tas var aizņemt vēl dažus CPU ciklus. Tomēr objektu dempings / atkļūdošana (pamata lietojums toString ()
) parasti tiek veikts izstrādes laikā un tiek izslēgts ražošanas videi. Dažos gadījumos šī izslēgšana ražošanas vidē var nebūt piemērojama, jo dažos projektos to var izmantot toString ()
biznesa loģikas vajadzībām. Es iesaku šo lēmumu pieņemt, balstoties uz katru projektu atsevišķi.
Pirms šīs utilītas izstrādes man jau bija domājusi šī izpildlaika elastība. Pirmkārt, es izstrādāju atsevišķu deleģēšanas klasi, kuru jebkura klienta klase izmantoja, lai izveidotu toString ()
. Klase to ģenerēja, izmantojot metodi, piemēram, atgriezties vietnē ToStringGenerator.generateToString (šis)
, kur šo
norāda uz klienta klases pašreizējo gadījumu un koda izraksts ir ierakstīts toString ()
metodes ieviešana. Bet šī pieeja neizdevās, jo Reflection API nav iespējas iegūt izpildes laikā privāto dalībnieku vērtības. Tātad klase bija noderīga tikai sabiedrības locekļiem, ko es nevēlējos.
Bet tad Sanscraint kungs norādīja, ka tas pats Reflection API kods izpildes laikā iegūst privāto dalībnieku vērtību, kad kods tiek ierakstīts vienas zvanītāja klases metodē. Tāpēc esmu atjauninājis lietderību, kas jāizmanto izpildlaikā, un papildus toString ()
metodi nekad nevajadzēs atjaunināt vai rediģēt, atņemot vai pievienojot jebkurus mērķa klases atribūtus.
Uzlabojums Nr. 3, ko ierosināja Ēriks Je
Sākotnēji es izmantoju šo
prefikss dalībnieku mainīgajiem piekļuvei ģenerētajā kodā, taču Ye kungs norādīja, ka kodu var izmantot arī statiskā metodē vai pat statisko dalībnieku izvadei. Tātad atjauninātais kods tagad var apstrādāt gan klases, gan instances dalībniekus. Ye kungs arī identificēja kļūdu, kas tika novērsta šajā versijā, kuras dēļ klase radīja bezjēdzīgu kodu neattiecināmām klasēm.
Kodu modifikācijas
Pēc lietderības runtime iespējošanas mani sarūgtināja tas, ka man vajadzēja kopēt / ielīmēt metodes katrā klasē, un tas kļuva sarežģīti, jo jaunais kods sastāvēja no vairākām metodēm.
Viens no risinājumiem būtu izveidot saskarni / abstraktu bāzes klasi, kas vismaz atrisinātu metodes parakstu problēmu, taču joprojām būtu nepieciešama kopēšana / ielīmēšana. Abstraktais bāzes klases risinājums arī ierobežotu klienta atvasinājumu no citas klases.
Iekšējai klasei tomēr ir iespēja piekļūt vecāku klases privātajiem locekļiem, tāpēc refleksijas kods, kas darbojas saskaņā ar tā metodēm, varētu iegūt arī privātās vērtības. Tāpēc es nolēmu nomainīt lietderību iekšējā klasē, kuru varētu ievietot jebkurā vecāku klientu klasē. Esmu arī nodrošinājis ToStringGeneratorExample.java, kas izmanto ToStringGenerator.java kā iekšējo klasi toString ()
metodi.
Visbeidzot, es vēlos pateikties tiem cilvēkiem, kuri piedāvāja savus ieteikumus šīs pieejas uzlabošanai.
Syed Fareed Ahmad ir Java programmētājs, dizainers un arhitekts Lahorā, Pakistānā. Viņš ir iesaistīts Java (Servlet, JSP un EJB), WebSphere un XML balstītu e-biznesa risinājumu izstrādē.Uzziniet vairāk par šo tēmu
- Turpmākajam avota kodam
//images.techhive.com/downloads/idge/imported/article/jvw/2000/08/jw-javatip99.zip
- Pārdomu dokumentācija Sun vietnē
//java.sun.com/products/jdk/1.1/docs/guide/reflection/index.html
- Skatīt visu iepriekšējo Java padomi un iesniedziet savu
//www.javaworld.com/javatips/jw-javatips.index.html
Šo stāstu “Java Tip 99: Automate toString () creation” sākotnēji publicēja JavaWorld.