Programavimas

„Java“ patarimas 99: automatizuokite toString () kūrimą

Kūrėjai, dirbantys prie didelių projektų, dažnai rašo naudingas valandas toString metodai. Net jei kiekviena klasė negauna savo toString metodas, kiekviena duomenų talpyklų klasė bus. Leidimas kiekvienam kūrėjui rašyti toString jo paties kelias gali sukelti chaosą; kiekvienas kūrėjas neabejotinai sugalvos unikalų formatą. Dėl to išvesties naudojimas derinimo metu tampa sunkesnis nei būtina be akivaizdžios naudos. Todėl kiekvienas projektas turėtų standartizuoti vieną formatą toString metodus ir tada automatizuoti jų kūrimą.

Automatizuokite „toString“

Dabar pademonstruosiu naudingumą, kuriuo galite tai padaryti. Šis įrankis automatiškai sukuria reguliarų ir tvirtą

toString

metodas nurodytai klasei, beveik pašalinant laiką, praleistą kuriant metodą. Ji taip pat centralizuoja

toString ()

formatas. Jei pakeisite formatą, turite atkurti

toString

metodai; tačiau tai vis tiek yra daug lengviau nei rankiniu būdu pakeisti šimtus ar tūkstančius klasių.

Taip pat lengva išlaikyti sugeneruotą kodą. Jei klasėse pridedate daugiau atributų, gali reikėti atlikti pakeitimus toString metodas taip pat. Nuo kartos toString metodai yra automatizuoti, norėdami atlikti pakeitimus, turite dar kartą paleisti klasės įrankį. Tai paprasčiau ir mažiau klaidų nei rankinis metodas.

Kodas

Šis straipsnis nėra skirtas paaiškinti „Reflection“ API; šiame kode daroma prielaida, kad jūs bent jau suprantate „Refleksijos“ sąvokas. Galite apsilankyti

Ištekliai

skyriuje „Reflection API“ dokumentacijai. Naudingumas rašomas taip:

paketas kainuoja.publikacijos.paslaugos; importuoti java.lang.reflect. *; public class ToStringGenerator {public static void main (String [] args) {if (args.length == 0) {System.out.println ("Pateikite klasės pavadinimą kaip komandinės eilutės argumentą"); System.exit (0); } pabandykite {Class targetClass = Class.forName (argumentai [0]); if (! targetClass.isPrimitive () && targetClass! = String.class) {Lauko laukai [] = targetClass.getDeclaredFields (); CSuper klasė = targetClass.getSuperclass (); // Gaunama super klasės išvestis ("StringBuffer buffer = new StringBuffer (500);"); // Buferio konstrukcija if (cSuper! = Null && cSuper! = Object.class) {output ("buffer.append (super.toString ());"); // Super klasės „toString ()}“ (int j = 0; j <laukai.length; j ++) {išvestis ("buffer.append (\" "+ laukai [j] .getName () +" = \ "); "); // Pridėti lauko pavadinimą, jei (laukai [j] .getType (). IsPrimitive () || laukai [j] .getType () == String.class) // Patikrinkite, ar nėra primityvios arba eilutės išvesties ("buffer.append ( tai. "+ laukai [j] .getName () +"); "); // Pridėti pirminę lauko vertę dar {/ * Tai NĖRA primityvus laukas, todėl tam reikia patikrinti suvestinio objekto * / output NULL vertę ("if (this." + Laukai [j] .getName () + "! = null)"); išvestis ("buffer.append (this." + laukai [j] .getName () + ".toString ());"); išvestis ("else buffer.append (\" reikšmė yra nulinė \ ");"); } // end of else} // ciklo išvesties pabaiga ("return buffer.toString ();"); }} catch (ClassNotFoundException e) {System.out.println ("Klasė nerasta klasės kelyje"); System.exit (0); }} privati ​​statinė tuštumos išvestis (eilutės duomenys) {System.out.println (duomenys); }} 

Kodo išvesties kanalas

Kodo formatas taip pat priklauso nuo jūsų projekto įrankio reikalavimų. Kai kurie kūrėjai gali norėti, kad kodas būtų vartotojo nustatytame faile diske. Kiti kūrėjai yra patenkinti

sistema.out

konsolė, leidžianti rankiniu būdu nukopijuoti ir įterpti kodą į tikrąjį failą. Aš paprasčiausiai palieku šias galimybes jums ir naudoju paprasčiausią metodą:

sistema.out

pareiškimus.

Metodo apribojimai

Yra du svarbūs šio požiūrio apribojimai. Pirmasis yra tai, kad jis nepalaiko objektų, kuriuose yra ciklų. Jei objekte A yra nuoroda į objektą B, kuriame yra nuoroda į objektą A, šis įrankis neveiks. Tačiau toks atvejis bus retas daugeliui projektų.

Antrasis apribojimas yra tas, kad norint pridėti ar atimti narių kintamuosius reikia atkurti toString metodas. Kadangi tai reikia padaryti su įrankiu arba be jo, tai nėra problema, būdinga šiam požiūriui.

Išvada

Šiame straipsnyje aš paaiškinau mažą automatikos įrankį, kuris tikrai gali pagerinti kūrėjų produktyvumą ir atlikti mažą, bet svarbų vaidmenį sumažinant bendrą projekto terminą.


Tolesni patarimai

Paskelbus šį patarimą, gavau keletą skaitytojų pasiūlymų, kaip patobulinti kodą. Toliau paaiškinsiu, kaip atnaujinau įrankį, remdamasis šiais pasiūlymais ir savo įžvalgomis. Šių patobulinimų šaltinio kodą galite rasti šaltiniuose.

Patobulinimas Nr. 1, pasiūlė Sangeeta Varma

Pirminiame kode nenagrinėjau objekto ir primityvių duomenų tipo masyvo tipų; naujas kodas dabar tvarko masyvo duomenis. Tačiau kodas eina tik iki vieno matmens masyvų ir neveiks kelių matmenų masyvams. Man nepavyko sugalvoti bendro šios problemos sprendimo, nes, kiek man žinoma, „Java“ duomenų tipų matmenų skaičius nėra ribojamas (vienintelis apribojimas yra turima atmintis). Džiaugiuosi bet kokiais atsiliepimais, kuriuos galite pasiūlyti sprendimui.

Patobulinimas Nr. 2, kurį pasiūlė Chrisas Sanscraintas

Iš pradžių pasiūliau naudingumą kūrimo laikui, o ne vykdymo aplinkai. Leisti programai veikti vykdymo metu gali būti labai patogu, tačiau gali prireikti dar kelių procesoriaus ciklų. Tačiau objekto dempingas / derinimas (pagrindinis "Windows 7" naudojimas) toString ()) paprastai atliekamas kūrimo metu ir yra išjungtas gamybos aplinkai. Kai kuriais atvejais šis išjungimas gamybos aplinkoje gali būti netaikomas, nes kai kurie projektai gali būti naudojami toString () verslo logikos tikslais. Siūlau tą sprendimą priimti kiekvienam projektui atskirai.

Prieš kurdamas šį įrankį galvoje jau turėjau šį vykdymo laiko lankstumą. Pirma, aš sukūriau atskirą delegavimo klasę, kurią naudojo bet kuri klientų klasė kuriant toString (). Klasė jį sukūrė naudodama metodo iškvietimą kaip grįžti į „ToStringGenerator.generateToString“ (tai), kur tai nurodo dabartinį kliento klasės egzempliorių, o kodo sakinys įrašomas toString () metodo įgyvendinimas. Bet šis metodas nepavyko, nes „Reflection“ API neturi galimybės gauti verčių privatiems nariams vykdymo metu. Taigi klasė buvo naudinga tik visuomenės nariams, ko aš nenorėjau.

Bet tada ponas Sanscraintasas atkreipė dėmesį į tai, kad tas pats „Reflection API“ kodas gauna privačių narių vertę vykdymo metu, kai kodas parašomas tos pačios skambintojų klasės metodu. Taigi aš atnaujinau naudingumo programą, kuri bus naudojama vykdymo metu, ir, be to, toString () metodo niekada nereikės atnaujinti ar redaguoti, norint atimti ar pridėti bet kokius tikslinės klasės atributus.

Patobulinimas Nr. 3, kurį pasiūlė Ericas Ye

Iš pradžių aš naudojau tai nario kintamųjų prieigos prie sugeneruoto kodo priešdėlis, tačiau p. Ye atkreipė dėmesį, kad kodas taip pat gali būti naudojamas statiniu metodu ar net statiniams nariams išvest. Taigi atnaujintas kodas dabar gali tvarkyti ir klasės, ir egzempliorių narius. Ponas Ye taip pat nustatė klaidą, kuri buvo ištaisyta šioje versijoje, dėl kurios klasė sugeneravo nenaudingą kodą nepriskirtoms klasėms.

Kodo modifikacijos

Po to, kai įjungiau naudingąjį vykdymą, buvau nusivylęs, kad turėjau nukopijuoti / įklijuoti metodus kiekvienoje klasėje. Tai tapo sunku, nes naują kodą sudarė keli metodai.

Vienas iš sprendimų būtų sukurti sąsają / abstrakčią pagrindinę klasę, kuri bent jau išspręstų metodo parašų problemą, tačiau vis tiek reikės kopijuoti / įklijuoti. Abstraktus bazinės klasės sprendimas taip pat kliudytų klientui gauti iš kitos klasės.

Tačiau vidinė klasė turi galimybę pasiekti privačius tėvų klasės narius, todėl pagal jos metodus veikiantis atspindėjimo kodas taip pat galėtų gauti privačias vertybes. Taigi nusprendžiau pakeisti naudingumą į vidinę klasę, kurią būtų galima įtraukti į bet kurią pagrindinių klientų klasę. Aš taip pat pateikiau ToStringGeneratorExample.java, kuri naudoja ToStringGenerator.java kaip vidinę klasę, kad įgyvendintų toString () metodas.

Galiausiai noriu padėkoti tiems žmonėms, kurie pateikė savo pasiūlymus dėl šio požiūrio tobulinimo.

Syedas Fareedas Ahmadas yra „Java“ programuotojas, dizaineris ir architektas Lahore, Pakistane. Jis dalyvauja kuriant „Java“ („Servlet“, „JSP“ ir „EJB“), „WebSphere“ ir XML pagrįstus el. Verslo sprendimus.

Sužinokite daugiau apie šią temą

  • Dėl tolesnio šaltinio kodo

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

  • Apmąstymo dokumentai „Sun“ svetainėje

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

  • Peržiūrėti visus ankstesnius „Java“ patarimai ir pateik savo

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

Šią istoriją „Java Tip 99: Automate toString () creation“ iš pradžių paskelbė „JavaWorld“.

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