Atelier de cod Java Strings

În acest atelier de cod vom testa cunoștințele dvs. despre Java Strings. În cadrul codului eșantion, variabilele String vor fi procesate în cadrul unei clase Java, care la rândul lor are o clasă interioară. Pentru a vă da seama ce se va întâmpla atunci când codul se execută, trebuie să înțelegeți nu numai elementele de bază ale șirului, ci și principiile obiectelor și claselor, precum și structurile de control, inclusiv metode, bucle și condiționări.

Când lucrați prin cod, amintiți-vă că programatorul care la scris poate avea greșeli în logica lor. Codul nu conține erori de sintaxă care vor arunca excepții la timpul de execuție, dar rezultatul nu poate fi neapărat intenția programatorului. Când lucrați la un proiect de programare, există șanse mari ca veți sfârși să lucrați cu codul altcuiva sau codul pe care l-ați scris la un moment dat în trecut și nu vă puteți aminti. Din păcate, noi, oamenii, nu avem tendința de a produce foarte des codul perfect, deci citirea cu un ochi critic este esențială.


Problema

Codul Java de mai jos reprezintă un fișier de clasă Java cu o clasă interioară în el. În cod, variabilele de text String sunt supuse mai multor procese diferite. Ce se întâmplă când se execută metoda constructorului StringFun? Lucrați prin cod și luați notă de ceea ce credeți că va fi scris prin declarațiile de ieșire ale sistemului la punctele A, B, C, D, E și F, având în vedere că oricare dintre acestea se poate executa mai mult de o dată. Puteți găsi mai ușor să folosiți un creion și o hârtie pentru a observa ce se întâmplă pe măsură ce codul progresează.

 clasa publică StringFun public StringFun () String initString = "abcdefghij"; StringWorker strWorker = StringWorker nou (initString); StringulStr = strWorker.getText (); System.out.println ("PUNCTUL A:" + theStr); strWorker.setText (strWorker.multiplyText (1, theStr)); System.out.println ("POINT B:" + strWorker.getText ()); int endPosn = initString.length () / 2; String endString = (TheStr.length ()> endPosn? TheStr.substring (0, endPosn): theStr); System.out.println ("PUNCT C:" + EndString); String altString = endString.concat (strWorker.getText ()); System.out.println ("PUNCTUL D:" + altString);  public class StringWorker privat String theText; private int maxLength; public StringWorker (String initText) theText = initText; maxLength = 5; shortenString (); multiplyText (2, TheText); System.out.println ("PUNCTUL E:" +Text);  void private shortenString () dacă (TheText.length ()> maxLength) TheText.substring (0, maxLength);  public String multiplyText (int multBy, String multText) StringBuilder sBuild = StringBuilder nou (multText); pentru (int i = 0; i 

Soluția

Aceasta este rezultatul extragerii când se execută metoda constructorului StringFun:

 PUNCTUL F: abcdefghij PUNCTUL E: abcdefghij PUNCTUL A: abcdefghij PUNCTUL F: abcdefghij PUNCTUL B: abcdefghijabcdefghij PUNCTUL C: abcde PUNCTUL D: abcdeabcdefghijabcdefghij

Observați ce variabilă String este scrisă în fiecare instrucțiune - uneori este variabila de instanță și uneori este o variabilă locală. Dacă acest lucru nu se potrivește cu ceea ce ați crezut că va fi produs, nu vă faceți griji. Codul este intenționat complicat. Dacă obțineți ieșirea corectă, bine făcută!


Note și explicații

Fișierul sursă atașat conține codul complet cu adnotări care explică ce se întâmplă în timpul execuției. Puteți obține o înțelegere mai bună prin compilarea și rularea programului și adăugarea de instrucțiuni de urmărire suplimentare, dacă descoperiți că ajută (adăugați fișierul sursă Java de clasă la un proiect și creați o instanță obiect a clasei StringFun pentru a începe).

Hai să trecem peste câteva dintre problemele de aici.

inflexibilitate

În metoda constructorului StringWorker este apelată metoda "shortenString". Deși această metodă apelează metoda substring pe variabila de instanță String, ea nu modifică valoarea acesteia. În Java, șirurile sunt imuabile. Aceasta înseamnă că atunci când modificați un String, Java creează de fapt un nou String. Metoda substring nu modifică String-ul pe care este apelat, dar copiază conținutul său într-un nou String cu modificarea substringului aplicată, returnând această nouă valoare String. Dacă apelul metodei secundare a fost modificat după cum urmează:

 theText = TheText.substring (0, maxLength);

Rezultatul ar fi diferit, deoarece variabila de instanță ar fi actualizată pentru a conține noul substring. Pe măsură ce codul se află, metoda returnează "abcde", dar nu face nimic cu ea.

Parametrii și returnări

O altă parte potențial complicată a codului este metoda "multiplyText". Confuzia este cauzată atât de metoda care are un nume necorespunzător, cât și de faptul că nu este utilizată în mod corespunzător. Dacă, în loc să lucrați prin conținutul metodei, ați interpretat intuitiv această metodă, ați presupune că scopul său ar fi multiplicarea textului cu numărul trecut ca parametru întreg. În realitate, metoda adaugă textul la sine că de multe ori, ceea ce înseamnă că rezultă într-o singură "perioadă" în sine decât s-ar putea aștepta. Numele de metode pot avea un impact imens asupra modului în care este utilizabilă o bibliotecă sau program Java, precum și numele variabilelor și ale claselor.

Metoda "multiplyText" este apelată de două ori în cod, o dată în constructorul StringFun și o dată în constructorul StringWorker. În constructorul StringWorker, codul nu face nimic cu Stringul returnat și astfel apelul metodic nu face nimic. Metoda "multiplyText" nu modifică variabila de instanță String. Ea efectuează modificări pe un string String, returnând rezultatul ca un nou String. Atunci când metoda "multiplyText" este apelată în constructorul StringFun, de această dată codul face ceva cu rezultatul - stabilește variabila de instanță StringWorker la String-ul returnat, folosind metoda "setText".

Aceste confuzii nu sunt doar un indicator al utilizării necorespunzătoare a unei metode, ci și un semn că metoda însăși este probabil proiectată și numită prost. Metoda "shortenString" modifică variabila instanței de clasă, în timp ce metoda "multiplyText" nu are niciun efect asupra variabilei de instanță. Indiferent dacă una sau ambele dintre acestea sunt adecvate depinde de scopul clasei din cadrul aplicației, dar numele lor trebuie să reflecte scopul lor într-un mod intuitiv de înțeles.

Ce variabilă?

Cealaltă sursă generală de confuzie din cod este faptul că avem de-a face cu mai multe variabile de clasă și locale diferite. De exemplu, dacă vă uitați la secțiunea din constructorul StringFun unde creăm o nouă variabilă locală numită "endString", veți vedea că aceasta procesează o variabilă numită "theStr" care a fost creată cu câteva rânduri înainte. Având în vedere procesarea care se întâmplă între aceste două secțiuni, se poate aștepta intuitiv ca secțiunea "endString" să proceseze variabila de instanță a obiectului nou modificată StringWorker și nu o variabilă locală anterioară. Prin urmare, codul pare contra-intuitiv, dar din nou, astfel de interpretări sunt îngreunate de lipsa de comentarii care indică scopul fiecărei clase sau a oricărei variabile.


Concluzie

OK, deci codul a avut câteva trucuri în el. Cu toate acestea, aceasta trebuie să reflecte realitatea muncii în multe proiecte Java. Chiar și cu cele mai bune intenții, majoritatea codului conține greșeli. Programele de proiectare sunt adesea supuse unor schimbări de plan care ajung la logica înșelătoare, precum și la variabile și metode care par confuze. Dacă codul este prost comentat sau nu este comentat deloc ca în exemplul de mai sus, acest lucru face lucrurile și mai rău.

Având abilitatea de a citi în mod realist codul și de a folosi măsuri practice, cum ar fi instrucțiunile de urmărire pentru a vedea ce se întâmplă în diferite puncte în timpul execuției, este un avantaj real în orice program de programare, precum și înțelegerea structurilor lingvistice.

Cod