1. Egenskaber: getters og sættere

Når et stort projekt udvikles af snesevis af programmører på samme tid, dukker der ofte problemer op, hvis de håndterer dataene, der er lagret i klassefelter, forskelligt.

Måske undlader folk at studere klassens dokumentation i detaljer, eller måske beskriver den ikke alle tilfælde. Som følge heraf er der hyppige situationer, hvor et objekts interne data kan blive "ødelagt", hvilket gør objektet ugyldigt.

For at undgå disse situationer er det sædvanligt at gøre alle klassefelter private i Java . Kun klassens metoder kan ændre klassens variabler. Ingen metoder fra andre klasser kan få direkte adgang til variablerne.

Hvis du ønsker, at andre klasser skal kunne hente eller ændre data inde i objekter i din klasse, skal du tilføje to metoder til din klasse - en get-metode og en sæt-metode. Eksempel:

Kode Bemærk
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 af feltet via konstruktøren


getName()— Denne metode returnerer værdien af ​​navnefeltet




setName()— Denne metode ændrer værdien af ​​navnefeltet

Ingen anden klasse kan ændre værdien af ​​navnefeltet direkte. Hvis nogen har brug for at få værdien af ​​navnefeltet, bliver de nødt til at kalde metoden getName() på et Personobjekt. Hvis en kode ønsker at ændre værdien af ​​navnefeltet, skal den kalde setName() metoden på et Personobjekt.

Metoden getName()kaldes også " getter for navnefeltet", og metoden setName()kaldes "sætteren for navnefeltet".

Dette er en meget almindelig tilgang. I 80-90% af al Java-kode vil du aldrig se offentlige variabler i en klasse. I stedet vil de blive erklæret private(eller protected), og hver variabel vil have offentlige gettere og sættere.

Denne tilgang gør koden længere, men mere pålidelig.

At få direkte adgang til en klassevariabel er som at dreje din bil gennem dobbelte gule linjer : det er nemmere og hurtigere, men hvis alle gør det, så bliver tingene værre for alle.

Lad os sige, at du vil oprette en klasse, der beskriver et punkt ( x, y). Sådan vil en nybegynder programmør gøre det:

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

Sådan ville en erfaren Java-programmør gøre 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 længere? Utvivlsomt.

Men du kan tilføje parametervalidering til gettere og sættere. For eksempel kan du sikre dig, at xog yaltid er større end nul (eller ikke mindre end nul). Eksempel:

Kode Bemærk
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 ved allerede, at objekter oprettes ved hjælp af newoperatoren, men hvordan slettes objekter? De eksisterer ikke for evigt. Der er ikke nok hukommelse til det.

I mange programmeringssprog, såsom C++, er der en speciel deleteoperator til at slette objekter. Men hvordan fungerer dette i Java?

I Java er alt indrettet lidt anderledes. Java har ingen delete-operator. Betyder det, at objekter ikke slettes i Java? Nej, de slettes selvfølgelig. Ellers ville Java-applikationer hurtigt løbe tør for hukommelse, og der ville ikke være tale om programmer, der kører uden afbrydelser i flere måneder.

I Java er sletningen af ​​objekter fuldstændig automatiseret. Java-maskinen håndterer selv sletning af objekter. Denne proces kaldes garbage collection, og mekanismen, der samler affald, kaldes garbage collector ( GC ).

Så hvordan ved Java-maskinen, hvornår den skal slette et objekt?

Skraldesamleren opdeler alle genstande i "tilgængelige" og "utilgængelige". Hvis der er mindst én reference til et objekt, anses det for at være tilgængeligt. Hvis der ikke er nogen variabel, der refererer til et objekt, betragtes objektet som uopnåeligt og erklæres for skrald, hvilket betyder, at det kan slettes.

I Java kan du ikke oprette en reference til et eksisterende objekt - du kan kun tildele referencer, som du allerede har. Hvis vi sletter alle referencer til et objekt, så er det tabt for altid.

Cirkulære referencer

Den logik lyder fantastisk, indtil vi støder på et simpelt modeksempel: antag, at vi har to objekter, der refererer til hinanden (lagre referencer til hinanden). Ingen andre objekter gemmer referencer til disse objekter.

Disse objekter kan ikke tilgås fra koden, men der refereres stadig til dem.

Dette er grunden til, at skraldeopsamleren opdeler objekter i tilgængelige og utilgængelige i stedet for "refererede" og "ikke-referencer".

Tilgængelige objekter

Først føjes objekter, der er 100 % i live, til listen, der kan nås. For eksempel den aktuelle tråd ( Thread.current()) eller konsollens InputStream ( System.in).

Derefter udvides listen over objekter, der kan nås, til at omfatte objekter, der refereres til af det indledende sæt af tilgængelige objekter. Derefter udvides det igen til at inkludere objekter, der refereres til af dette forstørrede sæt, og så videre.

Det betyder, at hvis der er nogle objekter, der kun refererer til hinanden, men der ikke er nogen måde at nå dem fra tilgængelige objekter, så vil disse objekter blive betragtet som skrald og vil blive slettet.


3. Affaldsindsamling

Hukommelsesfragmentering

Et andet vigtigt punkt relateret til objektsletning er hukommelsesfragmentering. Hvis du konstant opretter og sletter objekter, vil hukommelsen snart blive stærkt fragmenteret: områder med optaget hukommelse vil blive afbrudt med områder med ledig hukommelse.

Som et resultat kan vi nemt komme i en situation, hvor vi ikke kan skabe et stort objekt (f.eks. et array med en million elementer), fordi der ikke er en stor del af ledig hukommelse. Med andre ord kan der være ledig hukommelse, endda meget af den, men der er muligvis ikke en stor sammenhængende blok af ledig hukommelse

Hukommelsesoptimering (defragmentering)

Java-maskinen løser dette problem på en bestemt måde. Det ser sådan ud:

Hukommelsen er opdelt i to dele. Alle objekter oprettes (og slettes) i kun den ene halvdel af hukommelsen. Når det bliver tid til at rydde op i hullerne i hukommelsen, kopieres alle objekter i første halvdel til anden halvdel. Men de er kopieret lige ved siden af ​​hinanden, så der ikke er huller.

Processen ser nogenlunde sådan ud:

Trin 1: Efter oprettelse af objekter

Affaldsopsamling i Java

Trin 2: Udseende af "huller"

Affaldsopsamling i Java 2

Trin 3: Eliminering af "huller"

Affaldsopsamling i Java 3

Og det er derfor, du ikke behøver at slette objekter. Java-maskinen kopierer simpelthen alle tilgængelige objekter til en ny placering og frigør hele hukommelsesområdet, hvor objekterne plejede at blive gemt.