1. Egenskaper: getters og setters

Når et stort prosjekt utvikles av dusinvis av programmerere samtidig, dukker det ofte opp problemer hvis de håndterer dataene som er lagret i klassefelt annerledes.

Kanskje folk unnlater å studere klassedokumentasjonen i detalj, eller kanskje beskriver den ikke alle tilfeller. Som et resultat er det hyppige situasjoner når et objekts interne data kan bli "ødelagt", noe som gjør objektet ugyldig.

For å unngå disse situasjonene er det vanlig å gjøre alle klassefelt private i Java . Bare klassens metoder kan endre variablene til klassen. Ingen metoder fra andre klasser har direkte tilgang til variablene.

Hvis du vil at andre klasser skal kunne hente eller endre data i objekter i klassen din, må du legge til to metoder til klassen din - en get-metode og en sett-metode. Eksempel:

Kode Merk
class Person
{
   private String name;

   public Person(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
}


privatenavnefelt



Initialisering av feltet via konstruktøren


getName()— Denne metoden returnerer verdien av navnefeltet




setName()— Denne metoden endrer verdien på navnefeltet

Ingen annen klasse kan endre verdien av navnefeltet direkte. Hvis noen trenger å få verdien av navnefeltet, må de kalle metoden getName() på et Personobjekt. Hvis en kode ønsker å endre verdien av navnefeltet, må den kalle metoden setName() på et Personobjekt.

Metoden getName()kalles også " getter for navnefeltet", og metoden setName()kalles " setter for navnefeltet".

Dette er en veldig vanlig tilnærming. I 80-90 % av all Java-kode vil du aldri se offentlige variabler i en klasse. I stedet vil de bli deklarert private(eller protected), og hver variabel vil ha offentlige gettere og settere.

Denne tilnærmingen gjør koden lengre, men mer pålitelig.

Å få direkte tilgang til en klassevariabel er som å snu bilen din gjennom doble gule linjer : det er enklere og raskere, men hvis alle gjør det, blir det verre for alle.

La oss si at du vil lage en klasse som beskriver et punkt ( x, y). Slik vil en nybegynner programmerer gjøre det:

class Point
{
   public int x;
   public int y;
}

Slik ville en erfaren Java-programmerer gjort det:

Kode
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x;
      this.y = y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y;
   }
}

Er koden lengre? Utvilsomt.

Men du kan legge til parametervalidering til gettere og settere. For eksempel kan du sørge for at xog yalltid er større enn null (eller ikke mindre enn null). Eksempel:

Kode Merk
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x < 0 ? 0 : x;
      this.y = y < 0 ? 0 : y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x < 0 ?  0 : x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y < 0 ? 0 : y;
   }
}


2. Objektlevetid

Du vet allerede at objekter opprettes ved hjelp av newoperatoren, men hvordan slettes objekter? De eksisterer ikke for alltid. Det er ikke nok minne til det.

I mange programmeringsspråk, som C++, er det en spesiell deleteoperatør for å slette objekter. Men hvordan fungerer dette i Java?

I Java er alt ordnet litt annerledes. Java har ingen delete-operatør. Betyr dette at objekter ikke slettes i Java? Nei, de slettes selvfølgelig. Ellers ville Java-applikasjoner raskt gå tom for minne, og det ville ikke vært snakk om programmer som kjører uten avbrudd i flere måneder.

I Java er sletting av objekter fullstendig automatisert. Java-maskinen håndterer selv sletting av objekter. Denne prosessen kalles søppelinnsamling, og mekanismen som samler søppel kalles søppelsamleren ( GC ) .

Så hvordan vet Java-maskinen når den skal slette et objekt?

Søppelsamleren deler alle gjenstander inn i "reachable" og "unreachable". Hvis det er minst én referanse til et objekt, anses det som tilgjengelig. Hvis det ikke er noen variabel som refererer til et objekt, anses objektet som uoppnåelig og blir erklært som søppel, noe som betyr at det kan slettes.

I Java kan du ikke opprette en referanse til et eksisterende objekt - du kan bare tilordne referanser som du allerede har. Hvis vi sletter alle referanser til et objekt, er det tapt for alltid.

Sirkulære referanser

Den logikken høres bra ut til vi kommer over et enkelt moteksempel: anta at vi har to objekter som refererer til hverandre (lagre referanser til hverandre). Ingen andre objekter lagrer referanser til disse objektene.

Disse objektene kan ikke nås fra koden, men de er fortsatt referert.

Dette er grunnen til at søppelsamleren deler gjenstander inn i tilgjengelige og utilgjengelige i stedet for "refererte" og "urefererte".

Gjenstander som kan nås

Først blir objekter som er 100 % levende lagt til listen over tilgjengelige. For eksempel gjeldende tråd ( Thread.current()) eller konsollen InputStream ( System.in).

Deretter utvides listen over tilgjengelige objekter til å inkludere objekter som er referert til av det første settet med objekter som kan nås. Deretter utvides den igjen for å inkludere objekter som er referert til av dette forstørrede settet, og så videre.

Det betyr at hvis det er noen objekter som bare refererer til hverandre, men det er ingen måte å nå dem fra tilgjengelige objekter, vil disse objektene bli ansett som søppel og slettes.


3. Søppeltømming

Minnefragmentering

Et annet viktig poeng knyttet til objektsletting er minnefragmentering. Hvis du hele tiden oppretter og sletter objekter, vil minnet snart bli sterkt fragmentert: områder med okkupert minne vil bli ispedd områder med ledig minne.

Som et resultat kan vi lett komme i en situasjon der vi ikke kan lage et stort objekt (for eksempel en matrise med en million elementer), fordi det ikke er en stor del ledig minne. Med andre ord kan det være ledig minne, til og med mye av det, men det kan ikke være en stor sammenhengende blokk med ledig minne

Minneoptimalisering (defragmentering)

Java-maskinen løser dette problemet på en bestemt måte. Det ser omtrent slik ut:

Minnet er delt inn i to deler. Alle objekter opprettes (og slettes) i bare den ene halvdelen av minnet. Når det er på tide å rydde opp i hullene i minnet, kopieres alle objekter i første halvdel til andre halvdel. Men de er kopiert rett ved siden av hverandre slik at det ikke blir hull.

Prosessen ser omtrent slik ut:

Trinn 1: Etter å ha opprettet objekter

Søppelinnsamling i Java

Trinn 2: Utseendet til "hull"

Søppelsamling i Java 2

Trinn 3: Eliminering av "hull"

Søppelsamling i Java 3

Og det er derfor du ikke trenger å slette objekter. Java-maskinen kopierer ganske enkelt alle tilgjengelige objekter til et nytt sted, og frigjør hele minneområdet der objektene pleide å være lagret.