Programmēšana

Java padoms 99: automatizējiet toString () izveidi

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.

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