1. Sifat: getter dan setter

Apabila projek besar sedang dibangunkan oleh berpuluh-puluh pengaturcara pada masa yang sama, masalah sering timbul jika mereka mengendalikan data yang disimpan dalam medan kelas secara berbeza.

Mungkin orang gagal mengkaji dokumentasi kelas secara terperinci, atau mungkin ia tidak menerangkan setiap kes. Akibatnya, terdapat situasi yang kerap apabila data dalaman objek boleh menjadi "rosak", menjadikan objek itu tidak sah.

Untuk mengelakkan situasi ini, adalah kebiasaan untuk menjadikan semua medan kelas peribadi di Java . Hanya kaedah kelas boleh mengubah suai pembolehubah kelas. Tiada kaedah dari kelas lain boleh mengakses pembolehubah secara langsung.

Jika anda mahu kelas lain boleh mendapatkan atau menukar data di dalam objek kelas anda, anda perlu menambah dua kaedah pada kelas anda — kaedah dapatkan dan kaedah set. Contoh:

Kod Catatan
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;
   }
}


privatemedan nama



Permulaan medan melalui pembina


getName()— Kaedah ini mengembalikan nilai medan nama




setName()— Kaedah ini menukar nilai medan nama

Tiada kelas lain boleh menukar nilai medan nama secara langsung. Jika seseorang perlu mendapatkan nilai medan nama, mereka perlu memanggil getName() kaedah pada Personobjek. Jika sesetengah kod ingin menukar nilai medan nama, ia perlu memanggil setName() kaedah pada Personobjek.

Kaedah ini getName()juga dipanggil " pengambil untuk medan nama", dan setName()kaedah itu dipanggil " penetap untuk medan nama".

Ini adalah pendekatan yang sangat biasa. Dalam 80-90% daripada semua kod Java, anda tidak akan melihat pembolehubah awam dalam kelas. Sebaliknya, pembolehubah tersebut akan diisytiharkan private(atau protected), dan setiap pembolehubah akan mempunyai pengambil dan penetap awam.

Pendekatan ini menjadikan kod lebih panjang, tetapi lebih dipercayai.

Mengakses pembolehubah kelas secara langsung adalah seperti membelokkan kereta anda melalui garisan kuning berganda : ia lebih mudah dan lebih pantas, tetapi jika semua orang melakukannya, maka keadaan menjadi lebih teruk untuk semua orang.

Katakan anda ingin mencipta kelas yang menerangkan titik ( x, y). Begini cara pengaturcara baru melakukannya:

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

Begini cara pengaturcara Java yang berpengalaman melakukannya:

Kod
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;
   }
}

Adakah kod itu lebih panjang? Tidak dinafikan.

Tetapi anda boleh menambah pengesahan parameter pada getter dan setter. Sebagai contoh, anda boleh memastikan bahawa xdan ysentiasa lebih besar daripada sifar (atau tidak kurang daripada sifar). Contoh:

Kod Catatan
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. Seumur hidup objek

Anda sudah tahu bahawa objek dicipta menggunakan newoperator, tetapi bagaimanakah objek dipadamkan? Mereka tidak wujud selama-lamanya. Tidak ada ingatan yang cukup untuk itu.

Dalam banyak bahasa pengaturcaraan, seperti C++, terdapat deletepengendali khas untuk memadam objek. Tetapi bagaimana ini berfungsi di Jawa?

Di Jawa, semuanya diatur sedikit berbeza. Java tidak mempunyai pengendali padam. Adakah ini bermakna objek tidak dipadamkan di Jawa? Tidak, sudah tentu ia dipadamkan. Jika tidak, aplikasi Java akan cepat kehabisan memori, dan tidak akan ada sebarang perbincangan tentang program berjalan tanpa gangguan selama berbulan-bulan.

Di Jawa, pemadaman objek adalah automatik sepenuhnya. Mesin Java sendiri mengendalikan pemadaman objek. Proses ini dipanggil pengumpulan sampah, dan mekanisme yang mengumpul sampah dipanggil pemungut sampah ( GC ).

Jadi bagaimana mesin Java tahu bila hendak memadam objek?

Pengumpul sampah membahagikan semua objek kepada "boleh dicapai" dan "tidak boleh dicapai". Jika terdapat sekurang-kurangnya satu rujukan kepada objek, ia dianggap boleh dicapai. Jika tiada pembolehubah yang merujuk kepada objek, objek itu dianggap tidak boleh dicapai dan diisytiharkan sebagai sampah, yang bermaksud ia boleh dipadamkan.

Di Java, anda tidak boleh membuat rujukan kepada objek sedia ada — anda hanya boleh menetapkan rujukan yang anda sudah ada. Jika kita memadamkan semua rujukan kepada objek, maka ia akan hilang selama-lamanya.

Rujukan pekeliling

Logik itu kedengaran hebat sehingga kita mendapat contoh balas yang mudah: katakan kita mempunyai dua objek yang merujuk antara satu sama lain (menyimpan rujukan antara satu sama lain). Tiada objek lain yang menyimpan rujukan kepada objek ini.

Objek ini tidak boleh diakses daripada kod, tetapi ia masih dirujuk.

Inilah sebabnya mengapa pemungut sampah membahagikan objek kepada boleh dicapai dan tidak boleh dicapai daripada "dirujuk" dan "tidak dirujuk".

Objek yang boleh dicapai

Pertama, objek yang 100% hidup ditambahkan pada senarai yang boleh dicapai. Contohnya, benang semasa ( Thread.current()) atau konsol InputStream ( System.in).

Kemudian senarai objek boleh dicapai berkembang untuk memasukkan objek yang dirujuk oleh set awal objek boleh dicapai. Kemudian ia dikembangkan lagi untuk memasukkan objek yang dirujuk oleh set yang diperbesarkan ini, dan seterusnya.

Ini bermakna jika terdapat beberapa objek yang hanya merujuk antara satu sama lain, tetapi tidak ada cara untuk mencapainya daripada objek yang boleh dicapai, maka objek tersebut akan dianggap sampah dan akan dipadamkan.


3. Kutipan sampah

Pemecahan ingatan

Satu lagi perkara penting yang berkaitan dengan pemadaman objek ialah pemecahan memori. Jika anda sentiasa mencipta dan memadam objek, tidak lama lagi memori akan berpecah-belah: kawasan memori yang diduduki akan diselingi dengan kawasan memori yang tidak diduduki.

Akibatnya, kita boleh dengan mudah menghadapi situasi di mana kita tidak boleh mencipta objek besar (contohnya, tatasusunan dengan sejuta elemen), kerana tidak ada sebahagian besar memori bebas. Dalam erti kata lain, mungkin terdapat memori bebas, walaupun banyak, tetapi mungkin tidak terdapat blok memori bebas yang besar bersebelahan.

Pengoptimuman memori (defragmentasi)

Mesin Java menyelesaikan masalah ini dengan cara tertentu. Ia kelihatan seperti ini:

Ingatan terbahagi kepada dua bahagian. Semua objek dicipta (dan dipadamkan) dalam hanya separuh daripada memori. Apabila tiba masa untuk membersihkan lubang dalam ingatan, semua objek pada separuh pertama akan disalin ke separuh kedua. Tetapi mereka disalin betul-betul di sebelah satu sama lain supaya tidak ada lubang.

Prosesnya kelihatan lebih kurang seperti ini:

Langkah 1: Selepas mencipta objek

Pengumpulan sampah di Jawa

Langkah 2: Kemunculan "lubang"

Pengumpulan sampah di Jawa 2

Langkah 3: Penghapusan "lubang"

Pengumpulan sampah di Jawa 3

Dan itulah sebabnya anda tidak perlu memadam objek. Mesin Java hanya menyalin semua objek yang boleh dicapai ke lokasi baharu, dan membebaskan keseluruhan kawasan memori tempat objek disimpan.