Programavimas

„Java toString“ () aspektai

Net pradedantieji „Java“ kūrėjai žino apie „Object.toString ()“ metodo naudingumą, kuris yra prieinamas visiems „Java“ klasių egzemplioriams ir gali būti nepaisomas, kad pateiktų naudingos informacijos apie bet kurį konkretų „Java“ klasės egzempliorių. Deja, net patyrę „Java“ kūrėjai retkarčiais neišnaudoja šios galingos „Java“ funkcijos pranašumų dėl įvairių priežasčių. Šiame tinklaraščio įraše žvelgiu į kuklią „Java“ toString () ir aprašykite lengvus žingsnius, kuriuos galima atlikti siekiant pagerinti toString ().

Aiškiai įgyvendinkite (nepaisyti) toString ()

Bene svarbiausias aspektas, susijęs su maksimalios vertės pasiekimu nuo toString () yra jų įgyvendinimas. Nors visų „Java“ klasių hierarchijų šaknis „Object“ pateikia „toString“ () įdiegimą, kuris yra prieinamas visoms „Java“ klasėms, numatytasis šio metodo elgesys beveik niekada nėra naudingas. „Javadoc for Object.toString“ () paaiškina, kas pagal numatytuosius nustatymus teikiama „toString ()“, kai klasei nepateikiama pasirinktinė versija:

Metodas toString klasės objektui pateikia eilutę, susidedančią iš tos klasės, kurios objektas yra, pavadinimo, at-sign simbolio „@“ ir objekto maišos kodo nepasirašyto šešioliktainio atvaizdo. Kitaip tariant, šis metodas pateikia eilutę, lygią:getClass (). getName () + '@' + Integer.toHexString (hashCode ())

Sunku sugalvoti situaciją, kai naudingas klasės pavadinimas ir šešioliktainis objekto maišos kodo atvaizdavimas, atskirtas ženklu @. Beveik visais atvejais yra daug naudingiau pateikti individualų, aiškų

toString ()

diegimas klasėje, kad nepaisytų šios numatytosios versijos.

„Javadoc for Object.toString“ () taip pat nurodo, ką a toString () įgyvendinimas paprastai turėtų reikšti ir taip pat pateikia tą pačią rekomendaciją, kurią pateikiu čia: nepaisyti toString ():

ApskritaitoString metodas pateikia eilutę, kuri „tekstiškai reprezentuoja“ šį objektą. Rezultatas turėtų būti glaustas, bet informatyvus reprezentavimas, kurį žmogus gali lengvai perskaityti. Rekomenduojama, kad visi poklasiai nepaisytų šio metodo.

Kai tik rašau naują klasę, manau, kad tai yra keli metodai, kaip naujos klasės kūrimo dalis. Jie apima

hashCode ()

ir

lygus (objektas)

jei tinka. Tačiau, mano patirtis ir, mano nuomone, aiškus įgyvendinimas

toString ()

visada yra tinkamas.

Jei „Javadoc“ rekomendacijos, kad „visi poklasiai pakeičia šį metodą“, nepakanka (tada nemanau, kad mano rekomendacija taip pat yra), kad „Java“ kūrėjui būtų galima pagrįsti aiškios informacijos svarbą ir vertę toString () metodą, tada rekomenduoju peržiūrėti Josh Blocho efektyvų „Java“ elementą „Visada nepaisyti toString“, kad gautumėte papildomos informacijos apie diegimo svarbą. toString (). Mano nuomone, visiems „Java“ kūrėjams turėtų priklausyti jų kopija Veiksminga „Java“, bet laimei skyrius su šiuo punktu toString () yra prieinama tiems, kurie neturi kopijos: Visiems objektams bendri metodai.

Palaikyti / atnaujinti „Strings“ ()

Apmaudu, kai tiesiogiai ar netiesiogiai vadiname objektą toString () žurnalo sakinyje ar kitame diagnostikos įrankyje ir grąžinkite numatytąjį klasės pavadinimą ir objekto šešioliktainį maišos kodą, o ne ką nors naudingesnio ir įskaitomesnio. Beveik tiek pat apmaudu, kad yra neišsami toString () įgyvendinimas, kuris neapima reikšmingų objekto dabartinių savybių ir būsenos dalių. Stengiuosi būti pakankamai drausmingas ir sukurti bei laikytis įpročio visada peržiūrėti toString () įgyvendinimas kartu su lygus (objektas) ir hashCode () bet kurios klasės, kurioje dirbu, diegimai man yra nauji arba kai pridedu ar keičiu klasės atributus.

Tiesiog faktai (bet visi / dauguma jų!)

Skyriuje Veiksminga „Java“ anksčiau minėtas Blochas rašo: "Kai tai praktiškai įmanoma," toString "metodas turėtų pateikti visą įdomią objekte esančią informaciją". Gali būti skausminga ir varginantis pridėti visus atributus sunkios klasės atributus prie toString diegimo, tačiau vertybė tiems, kurie bando derinti ir diagnozuoti su ta klase susijusias problemas, bus verta. Paprastai siekiu, kad sugeneruotoje „String“ reprezentacijoje būtų visi reikšmingi nenuoseklūs mano egzemplioriaus atributai (o kartais įtraukiu ir tai, kad kai kurie atributai yra niekiniai). Aš taip pat paprastai pridedu minimalų atributų identifikavimo tekstą. Daugeliu atžvilgių tai daugiau menas nei mokslas, tačiau stengiuosi įtraukti pakankamai teksto, kad atributai būtų diferencijuoti, neišaiškinant būsimų kūrėjų per daug detalių. Man svarbiausia sutvarkyti atributų reikšmes ir tam tikro tipo identifikavimo raktą.

Pažink savo auditoriją

Viena iš dažniausiai pasitaikančių klaidų, kurias mačiau ne pradedantiesiems „Java“ kūrėjams toString () yra pamiršti ką ir kas toString () paprastai yra skirtas. Apskritai, toString () yra diagnostikos ir derinimo įrankis, leidžiantis lengvai užregistruoti išsamią informaciją apie konkretų egzempliorių tam tikru metu, kad vėliau būtų galima derinti ir diagnostiką. Paprastai yra klaida, jei vartotojo sąsajos rodo eilutes, kurias sugeneruoja toString () arba priimti loginius sprendimus remiantis a toString () atstovavimas (iš tikrųjų loginių sprendimų priėmimas dėl bet kurios stygos yra trapus!). Aš mačiau geranoriškų kūrėjų toString () grąžinti XML formatą, skirtą naudoti kitam XML tinkamam kodo aspektui. Kita reikšminga klaida yra priversti klientus analizuoti grįžusią eilutę toString () siekiant sistemingai pasiekti duomenų narius. Tikriausiai geriau pateikti viešojo „getter“ / „accessor“ metodą, nei pasikliauti toString () niekada nesikeičia. Visa tai yra klaidos, nes šie metodai pamiršta a toString () įgyvendinimas. Tai ypač klastinga, jei kūrėjas pašalina svarbias savybes iš toString () metodas (žr. paskutinį elementą), kad jis geriau atrodytų vartotojo sąsajoje.

man patinka toString () diegimai, kad būtų visos svarbios detalės ir kad būtų kuo mažiau formatuojama, kad šios detalės būtų malonesnės. Šiame formatavime gali būti apgalvotai parinktų naujų eilučių simbolių [System.getProperty ("line.seperator");] ir skirtukus, dvitaškius, kabliataškius ir kt. Aš neinvestuoju tiek laiko, kiek investuočiau į galutiniam programinės įrangos vartotojui pateiktą rezultatą, bet stengiuosi, kad formatavimas būtų pakankamai gražus, kad būtų daugiau skaitomas. Stengiuosi įgyvendinti toString () metodai, kurių priežiūra nėra pernelyg sudėtinga ar brangu, tačiau kurie pateikia labai paprastą formatavimą. Bandau elgtis su būsimais savo kodo prižiūrėtojais taip, kaip norėčiau, kad su manimi elgtųsi kūrėjai, kurių kodą vieną dieną išlaikysiu.

Savo punkte apie toString () „Bloch“ teigia, kad kūrėjas turėtų pasirinkti, ar turėti toString () grąžinti konkretų formatą. Jei numatomas konkretus formatas, tai turėtų būti dokumentuota „Javadoc“ komentaruose, o Blochas taip pat rekomenduoja pateikti statinį inicializatorių, kuris galėtų grąžinti objektui jo egzemplioriaus charakteristikas, pagrįstas eilute, kurią sugeneravo „Javadoc“. toString (). Aš sutinku su viskuo, bet manau, kad tai yra daugiau problemų, nei dauguma kūrėjų nori eiti. Blochas taip pat atkreipia dėmesį į tai, kad bet kokie šio formato pakeitimai būsimuose leidimuose sukels skausmą ir pyktį žmonėms, priklausomai nuo to (būtent todėl nemanau, kad logika priklauso nuo toString () produkcija). Turint didelę drausmę rašyti ir prižiūrėti atitinkamus dokumentus, turint iš anksto nustatytą a toString () gali būti tikėtina. Tačiau man atrodo bėda ir geriau tiesiog sukurti naują ir atskirą metodą tokiems tikslams ir palikti toString () neapkrautas.

Netoleruojamas šalutinis poveikis

Toks pat svarbus kaip ir toString () Tai yra nepriimtina (ir tikrai laikoma bloga forma) aiškus ar numanomas raginimas toString () poveikio logiką arba sukelti išimčių ar logikos problemų. Autorius a toString () metodas turėtų būti atsargus, kad prieš prieigą prie jų būtų patikrinta, ar nuorodos nėra niekinės, kad būtų išvengta „NullPointerException“. Daugelį taktikų, kurias aprašiau įraše „Efektyvus„ Java NullPointerException Handling “, galima naudoti toString () įgyvendinimas. Pavyzdžiui, String.valueOf (Object) suteikia lengvą mechanizmą, leidžiantį visiškai apsaugoti abejotinos kilmės atributus.

Panašiai svarbu ir toString () kūrėjas, prieš bandydamas pasiekti elementus, esančius už tos kolekcijos ribų, patikrins masyvo dydžius ir kitus kolekcijos dydžius. Visų pirma, per daug lengva paleisti „StringIndexOutOfBoundsException“, kai bandoma manipuliuoti „String“ reikšmėmis naudojant „String.substring“.

Nes daikto toString () diegimas gali būti lengvai naudojamas, sąmoningai to nesuvokiant, šis patarimas, siekiant įsitikinti, kad jis nemeta išimčių ir neatlieka logikos (ypač logiką keičiančios būsenos), yra ypač svarbus. Paskutinis dalykas, ko tik nori, yra tai, kad registruojant dabartinę egzemplioriaus būseną, išimtis arba pasikeičia būsena ir elgesys. A toString () diegimas turėtų būti veiksminga tik skaityti, kai objekto būsena yra skaitoma, kad būtų sukurta grąžinimo eilutė. Jei proceso metu pasikeis kokie nors atributai, blogi dalykai greičiausiai nutiks nenuspėjamu metu.

Tai mano pozicija, kad a toString () diegimas turėtų apimti būseną tik sugeneruotoje eilutėje, kuri prieinama toje pačioje proceso erdvėje jos generavimo metu. Man nepateisinama turėti toString () diegimo prieiga prie nuotolinių paslaugų, kad būtų sukurta egzemplioriaus eilutė. Gal kiek mažiau akivaizdu yra tai, kad egzempliorius neturėtų pildyti duomenų atributų, nes toString () buvo vadinamas. toString () įgyvendinant turėtų būti pranešama tik apie tai, kaip viskas yra šiuo metu, o ne apie tai, kaip gali būti ar bus ateityje, jei atsiras tam tikrų skirtingų scenarijų arba jei viskas bus pakrauta. Siekdama efektyviai derinti ir diagnozuoti, toString () turi parodyti, kaip yra sąlygos, o ne kaip galėtų būti.

Nuoširdžiai vertinamas paprastas formatavimas

Kaip aprašyta aukščiau, protingas eilučių skiriamųjų elementų ir skirtukų naudojimas gali būti naudingas, kai ilgos ir sudėtingos egzemplioriai tampa malonesni, kai sugeneruojami String formatu. Yra ir kitų „gudrybių“, kurios gali padaryti viską gražesnį. Ne tik daro String.valueOf (objektas) pateikti kai kuriuos niekinis apsauga, tačiau ji taip pat suteikia niekinis kaip eilutė „null“ (kuri dažnai yra pirmenybė teikiama nuliui toString () sugeneruotoje eilutėje. Arrays.toString (objektas) yra naudinga norint lengvai pateikti masyvus kaip eilutes (jei reikia daugiau informacijos, žr.

Į „ToString“ atstovavimą įtraukite klasės pavadinimą

Kaip aprašyta aukščiau, numatytasis toString () pateikia klasės pavadinimą kaip egzemplioriaus reprezentacijos dalį. Aiškiai nepaisydami to, galime pamesti šio klasės pavadinimą. Paprastai tai nėra didelė problema, jei registruojate egzempliorių eilutę, nes registravimo sistemoje bus klasės pavadinimas. Tačiau aš norėčiau būti saugus ir visada turėti klasės pavadinimą. Man nerūpi, kad šešioliktainis maišos kodo atvaizdavimas būtų paliktas nuo numatytojo toString (), bet klasės pavadinimas gali būti naudingas. Geras to pavyzdys yra „Throwable.toString“). Aš norėčiau naudoti šį metodą, o ne „getMessage“ ar „getLocalizedMessage“, nes pirmasis (toString ()) apima Metamasklasės pavadinimas, o pastarieji du metodai - ne.

toString () alternatyvos

Šiuo metu mes to neturime (bent jau ne standartinio požiūrio), tačiau buvo kalbėta apie „Java“ objektų klasę, kuri ilgai siektų saugiai ir naudingai paruošti įvairių objektų, duomenų struktūrų ir rinkinių eilutes. Nesu girdėjęs apie pastarąją JDK7 pažangą šioje klasėje. Standartinė JDK klasė, teikianti objektų eilutę, net jei objektų klasės apibrėžimai nepateikė aiškaus toString () būtų naudinga.

„Apache Commons ToStringBuilder“ gali būti populiariausias sprendimas kuriant saugius „toString“) diegimus su keletu pagrindinių formatavimo valdiklių. Anksčiau rašiau tinklaraštį „ToStringBuilder“ ir yra daugybė kitų internetinių šaltinių, susijusių su „ToStringBuilder“ naudojimu.

Gleno McCluskey'o „Java Technology Tech“ patarime „Writing toString Methods“ pateikiama papildoma informacija, kaip parašyti gerą toString () metodą. Viename iš skaitytojų komentarų Giovanni Pelosi teigia, kad pirmenybė teikiama eilutės egzemplioriaus pateikimo paveldėjimo hierarchijose pateikimui iš toString () į tam tikslui sukurtą delegatų klasę.

Išvada

Manau, kad dauguma „Java“ kūrėjų pripažįsta gėrio vertę toString () įgyvendinimai. Deja, šie įgyvendinimai ne visada yra tokie geri ar naudingi, kokie galėtų būti. Šiame įraše bandžiau apibūdinti keletą tobulinimo aspektų toString () įgyvendinimai. Nors a toString () metodas neturės (arba bent jau neturėtų) paveikti logikos kaip lygus (objektas) arba hashCode () metodas gali pagerinti derinimą ir diagnostikos efektyvumą. Mažiau laiko praleidus suprantant objekto būseną reiškia daugiau laiko išspręsti problemą, pereiti prie įdomesnių iššūkių ir patenkinti daugiau klientų poreikių.

Šią istoriją „Java toString () svarstymai“ iš pradžių paskelbė „JavaWorld“.