1. Tulajdonságok: getterek és szetterek

Amikor egy nagy projektet egyszerre több tucat programozó fejleszt, akkor gyakran problémák merülnek fel, ha másképp kezelik az osztálymezőkben tárolt adatokat.

Lehet, hogy az emberek nem tanulmányozzák részletesen az osztály dokumentációját, vagy nem ír le minden esetet. Ennek eredményeként gyakran előfordulnak olyan helyzetek, amikor egy objektum belső adatai "sérülhetnek", ami érvénytelenné teszi az objektumot.

Az ilyen helyzetek elkerülése érdekében a Java-ban szokás minden osztálymezőt priváttá tenni . Csak az osztály metódusai módosíthatják az osztály változóit. Más osztályokból származó metódusok nem férhetnek hozzá közvetlenül a változókhoz.

Ha azt szeretné, hogy más osztályok is hozzáférhessenek vagy módosíthassanak az osztályának objektumain belüli adatokat, két metódust kell hozzáadnia az osztályhoz – egy get metódust és egy set metódust. Példa:

Kód jegyzet
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;
   }
}


privatenév mező



A mező inicializálása a konstruktoron keresztül


getName()— Ez a metódus a névmező értékét adja vissza




setName()— Ez a metódus megváltoztatja a névmező értékét

Más osztály nem tudja közvetlenül megváltoztatni a névmező értékét. Ha valakinek meg kell szereznie a név mező értékét, akkor meg kell hívnia a getName() metódust egy Personobjektumon. Ha valamilyen kód meg akarja változtatni a névmező értékét, akkor meg kell hívnia a setName() metódust egy Personobjektumon.

A metódust " névmező getterénekgetName() " is nevezik , a metódust pedig " névmező beállítójának" .setName()

Ez egy nagyon elterjedt megközelítés. Az összes Java kód 80-90%-ában soha nem fogsz nyilvános változókat látni egy osztályban. Ehelyett deklarálva lesznek private(vagy protected), és minden változónak nyilvános getterei és beállítói lesznek.

Ez a megközelítés hosszabb, de megbízhatóbbá teszi a kódot.

Az osztályváltozók közvetlen elérése olyan, mintha dupla sárga vonalon átfordítaná az autót : könnyebb és gyorsabb, de ha mindenki megteszi, akkor mindenki számára rosszabb lesz a helyzet.

Tegyük fel, hogy szeretne létrehozni egy osztályt, amely leír egy pontot ( x, y). Íme, hogyan csinálná egy kezdő programozó:

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

Íme, hogyan csinálná egy tapasztalt Java programozó:

Kód
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;
   }
}

Hosszabb a kód? Kétségtelenül.

De hozzáadhat paraméterellenőrzést a getterekhez és a beállítókhoz. Például megbizonyosodhat arról, hogy xés yértéke mindig nagyobb, mint nulla (vagy nem kisebb nullánál). Példa:

Kód jegyzet
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. Az objektum élettartama

Már tudja, hogy az objektumok az newoperátor segítségével jönnek létre, de hogyan törlődnek az objektumok? Nem léteznek örökké. Nincs elég memória ehhez.

Számos programozási nyelvben, például a C++-ban, létezik egy speciális deleteoperátor az objektumok törlésére. De hogyan működik ez a Java-ban?

A Java nyelven minden kicsit másképp van elrendezve. A Java-nak nincs delete operátora. Ez azt jelenti, hogy a Java-ban nem törlődnek az objektumok? Nem, természetesen törölve vannak. Ellenkező esetben a Java alkalmazásokból gyorsan elfogyna a memória, és szó sem lehet arról, hogy a programok hónapokig megszakítás nélkül futnak.

Java nyelven az objektumok törlése teljesen automatizált. A Java gép maga kezeli az objektumok törlését. Ezt a folyamatot szemétgyűjtésnek, a szemetet gyűjtő mechanizmust pedig szemétgyűjtőnek ( GC ) nevezik .

Tehát honnan tudja a Java gép, hogy mikor kell törölnie egy objektumot?

A szemétgyűjtő minden tárgyat "elérhető" és "elérhetetlen" részekre oszt. Ha van legalább egy hivatkozás egy objektumra, akkor az elérhetőnek minősül. Ha nincs olyan változó, amely egy objektumra hivatkozik, akkor az objektumot elérhetetlennek tekintik, és szemétnek nyilvánítják, ami azt jelenti, hogy törölhető.

Java nyelven nem hozhat létre hivatkozást egy meglévő objektumhoz – csak a már meglévő hivatkozásokat rendelheti hozzá. Ha törölünk minden hivatkozást egy objektumra, akkor az örökre elveszik.

Körhivatkozások

Ez a logika jól hangzik egészen addig, amíg nem találunk egy egyszerű ellenpéldát: tegyük fel, hogy van két objektumunk, amelyek egymásra hivatkoznak (egymásra utaló hivatkozásokat tárolunk). Más objektumok nem tárolnak hivatkozásokat ezekre az objektumokra.

Ezek az objektumok nem érhetők el a kódból, de továbbra is hivatkoznak rájuk.

Ez az oka annak, hogy a szemétgyűjtő felosztja a tárgyakat elérhetőre és elérhetetlenre, ahelyett, hogy "hivatkozott" és "nem hivatkozott".

Elérhető tárgyak

Először a 100%-ban élő objektumok kerülnek az elérhető listára. Például az aktuális szál ( Thread.current()) vagy a konzol InputStream ( System.in).

Ezután az elérhető objektumok listája kibővül olyan objektumokkal, amelyekre az elérhető objektumok kezdeti készlete hivatkozik. Ezután ismét kibővül, hogy tartalmazza azokat az objektumokat, amelyekre ez a kinagyított halmaz hivatkozik, és így tovább.

Ez azt jelenti, hogy ha vannak olyan objektumok, amelyek csak egymásra hivatkoznak, de az elérhető objektumokról nem lehet elérni őket, akkor ezek az objektumok szemétnek minősülnek, és törlődnek.


3. Szemétgyűjtés

Az emlékezet töredezettsége

Az objektumtörléssel kapcsolatos másik fontos pont a memória töredezettsége. Ha folyamatosan hoz létre és töröl objektumokat, a memória hamarosan erősen töredezett lesz: a foglalt memóriaterületeket a nem foglalt memóriaterületekkel tarkítják.

Emiatt könnyen kerülhetünk olyan helyzetbe, hogy nem tudunk nagy objektumot létrehozni (például millió elemű tömböt), mert nincs egy nagy darab szabad memória. Más szavakkal, lehet, hogy van szabad memória, akár sok is, de lehet, hogy nincs nagy összefüggő szabad memóriablokk.

Memória optimalizálás (töredezettségmentesítés)

A Java gép ezt a problémát sajátos módon oldja meg. Valahogy így néz ki:

A memória két részre oszlik. Minden objektum létrehozása (és törlése) csak a memória felében történik. Amikor eljön az idő, hogy kitisztítsuk a memória lyukait, az első felében lévő összes objektumot a rendszer átmásolja a második felébe. De közvetlenül egymás mellé vannak másolva, hogy ne legyenek lyukak.

A folyamat nagyjából így néz ki:

1. lépés: Az objektumok létrehozása után

Szemétgyűjtés Java nyelven

2. lépés: "lyukak" megjelenése

Szemétgyűjtés Java 2-ben

3. lépés: A "lyukak" megszüntetése

Szemétgyűjtés Java 3-ban

És ezért nem kell objektumokat törölnie. A Java gép egyszerűen átmásolja az összes elérhető objektumot egy új helyre, és felszabadítja a teljes memóriaterületet, ahol az objektumokat korábban tárolták.