Sunday, March 25, 2018

12.Enumerasi dan Autoboxing Bagian Satu



Bab ini akan mendiskusikan dua fitur yang relatif baru pada bahasa Java: enumerasi dan autoboxing. Setiap fitur ini memperluas kekuatan Java seperti yang akan dijelaskan pada bab ini. 


Enumerasi
Versi Java sebelum JDK 5 memiliki kekurangan satu fitur yang dirasakan oleh banyak programer: enumerasi. Pada bentuknya yang paling sederhana, enumerasi merupakan sebuah daftar yang berisi konstanta-konstanta. Meskipun Java menawarkan fitur lain yang menyediakan fungsionalitas yang cukup sama, seperti variabel final, banyak programer masih merindukan kemurnian konseptual dari enumerasi, khususnya karena enumerasi didukung oleh banyak bahasa lain. Mulai dari JDK 5, enumerasi ditambahkan pada bahasa Java, dan sekarang telah menjadi bagian integral dari Java.


Dasar-Dasar Enumerasi
Sebuah enumerasi diciptakan menggunakan katakunci enum. Misalnya, berikut adalah sebuah enumerasi sederhana yang memuat sejumlah sejumlah kota di Indonesia:

// Sebuah enumerasi dari varietas kota.
enum Kota {
   Malang, Medan, Jakarta, Jogja, Bandung
}

Pengenal Malang, Medan dan seterusnya dinamakan dengan konstanta enumerasi. Setiap konstanta ini secara implisit dideklarasikan sebagai anggota static, final, dan public dari enumerasi Kota. Selain itu, tipe datanya adalah tipe data enumerasi dimana ia dideklarasikan, dimana pada kasus ini tipe datanya adalah Kota. Jadi, pada bahasa Java, konstanta-konstanta ini dinamakan dengan tipe data diri, dimana “diri” mengacu pada enumerasi pengapit.

Setelah Anda mendefinisikan sebuah enumerasi, Anda dapat menciptakan sebuah variabel dengan tipe data itu. Namun, meskipun enumerasi mendefinisikan tipe data kelas, Anda tidak bisa menginstansiasi (menciptakan objek) enum menggunakan operator new. Tetapi, Anda bisa mendeklarasikan dan menggunakan variabel enumerasi dengan cara yang hampir sama dengan ketika Anda menggunakan tipe data primitif. Sebagai contoh, statemen berikut mendeklarasikan kt sebagai sebuah variabel bertipe data Kota:

Kota kt;

Karena kt adalah variabel bertipe Kota, nilai-nilai yang bisa ditugaskan kepadanya (atau yang dapat dimuatnya) adalah konstanta-konstanta yang didefinisikan oleh enumerasi tersebut. Sebagai contoh, statemen ini menugaskan nilai Malang kepada kt:

kt = Kota.Malang;

Perhatikan bahwa simbol Malang diawali dengan Kota.

Dua konstanta enumerasi dapat dibandingkan kesamaannya menggunakan operator relasional. Misalnya, statemen ini membandingkan nilai pada kt dengan konstanta Malang:

if(kt == Kota.Malang)  //…

Sebuah nilai enumerasi dapat pula dipakai untuk mengendalikan statemen switch. Tentu, semua statemen case harus menggunakan konstanta dari enum yang sama seperti yang dipakai oleh ekspresi switch. Sebagai contoh, switch ini sama sekali valid untuk digunakan:

// Menggunakan enum untuk mengendalikan statemen switch
switch(kt) {
case Malang:
   //…
case Medan:
   //…

Perhatikan bahwa pada tiap statemen case, nama dari konstanta enumerasi dipakai tanpa menyebutkan nama tipe enumerasinya. Jadi, Jakarta, bukan Kota.Jakarta, yang digunakan. Ini karena tipe enumerasi pada ekspresi switch secara implisit telah ditetapkan tipe enum dari konstanta case. Jadi, tidak diperlukan menyebutkan nama tipe enum pada statemen case.

Ketika konstanta enumerasi ditampilkan, seperti pada statemen println(), nama konstanta tersebut akan ditampilkan. Misalnya, jika diberikan statemen ini:

System.out.println(Kota.Bandung);

Maka Bandung akan ditampilkan di layar monitor.

Program berikut mengilustrasikan semua konsep yang telah dijelaskan sejauh ini dan mendemonstrasikan enumerasi Kota:

// Sebuah enumerasi yang memuat nama-nama kota di Indonesia.
enum Kota {
   Malang, Medan, Jakarta, Jogja, Bandung
}

public class DemoEnum {
   public static void main(String args[])
   {
      Kota kt;
      kt = Kota.Jakarta;
 
      // Menampilkan sebuah nilai enum.
      System.out.println("Nilai dari kt: " + kt);
      System.out.println();
 
      kt = Kota.Bandung;
 
      // Membandingkan dua nilai enum.
   if(kt == Kota.Bandung)
         System.out.println("kt memuat Bandung.\n");
 
   // Menggunakan sebuah enum untuk mengendalikan switch.
      switch(kt) {
      case Malang:
            System.out.println("Apel malang nikmat rasanya.");
            break;
         case Medan:
            System.out.println("Danau toba dekat dengan Medan.");
            break;
         case Jakarta:
            System.out.println("Monas ciri khas kota Jakarta.");
            break;
         case Jogja:
            System.out.println("Jogja memiliki wisata Malioboro.");
            break;
         case Bandung:
            System.out.println("Bandung kota sejuta seniman.");
            break;
      }
   }
}

Keluaran dari program ini ditampilkan berikut:

Nilai dari kt: Jakarta

kt memuat Bandung.

Bandung kota sejuta seniman.


Metode values() dan valueOf()
Semua enumerasi secara otomasi memuat dua metode pustaka: values() dan valueOf(). Bentuk umumnya ditunjukkan berikut:

public static tipe-enum[ ] values()
public static tipe-enum[ ] valueOf(String str)

Metode values() menghasilkan sebuah array yang memuat konstanta-konstanta enumerasi. Metode valueOf() menghasilkan konstanta enumerasi yang memiliki nilai yang berkaitan dengan string yang dilewatkan pada str. Pada kedua kasus, tipe-enum adalah tipe enumerasi. Sebagai contoh, pada kasus enumerasi Kota yang ditunjukkan sebelumnya, tipe nilai balik dari Kota.valueOf(“Jakarta”) adalah Jakarta.

Program berikut mendemonstrasikan metode values() dan valueOf():

// Menggunakan metode-metode pustaka dari enumerasi

// Sebuah enumerasi yang memuat nama-nama kota di Indonesia.
enum Kota {
   Malang, Medan, Jakarta, Jogja, Bandung
}

public class DemoEnum2 {
   public static void main(String args[])
   {
    Kota kt;
   
      System.out.println("Berikuat adalah semua konstanta Kota:");

      // menggunakan values()
      Kota arrayKota[] = Kota.values();
      for(Kota a : arrayKota)
         System.out.println(a);
      System.out.println();
 
      // menggunakan valueOf()
      kt = Kota.valueOf("Jakarta");
      System.out.println("kt memuat " + kt);
   }
}

Program tersebut di atas menghasilkan keluaran berikut:

Berikuat adalah semua konstanta Kota:
Malang
Medan
Jakarta
Jogja
Bandung

kt memuat Jakarta

Perhatikan bahwa program ini menggunakan sebuah loop for for-each untuk menjejak array yang memuat konstanta-konstanta yang diperoleh dengan memanggil values(). Untuk ilustrasi, variabel arrayKota diciptakan dan ditugasi sebuah referensi yang menunjuk ke array enumerasi. Namun, langkah ini tidak penting karena for sebenarnya dapat dituliskan seperti ditunjukkan di sini, yang mengeliminasi kebutuhan akan variabel arrayKota:

for(Kota a : Kota.values())
   System.out.println(a);

Sekarang, perhatikan bagaimana nilai yang melekat pada nama Jakarta didapatkan dengan memanggil valueOf():

kt = Kota.valueOf("Jakarta");

Seperti dijelaskan, valueOf() menghasilkan nilai enumerasi yang berkaitan dengan nama konstanta yang direpresentasikan sebagai sebuah string.


Enumerasi Java Adalah Tipe Data Kelas
Seperti disebutkan, enumerasi Java adalah tipe data kelas. Meskipun Anda tidak bisa menciptakan objek enum menggunakan operator new, enumerasi memiliki banyak kapabilitas seperti kelas biasa. Fakta bahwa enum bisa mendefinisikan sebuah kelas memberikan kekuatan luar biasa pada enumerasi Java. Sebagai contoh, Anda dapat memberikannya konstruktor, variabel dan metode, bahkan bisa pula mengimplementasikan antarmuka.

Adalah penting untuk memahami bahwa setiap konstanta enumerasi adalah sebuah objek dari tipe enumerasinya. Jadi, ketika Anda mendefinisikan sebuah konstruktor untuk enum, konstruktor itu dipanggil ketika tiap konstanta enumerasi diciptakan. Selain itu, setiap konstanta enumerasi memiliki salinan sendiri atas semua variabel objek enumerasi. Sebagai contoh, perhatikan versi program berikut dari Kota:

// Menggunakan konstruktor, variabel, dan metode dari enumerasi.

// Sebuah enumerasi yang memuat nama-nama kota di Indonesia.
enum Kota {
   Malang(3), Medan(5), Jakarta(15), Jogja(7), Bandung(9);

   private int penduduk; // banyak penduduk

 // Konstruktor
   Kota(int p) {penduduk = p; }
    
   // Metode
   int getPenduduk() { return penduduk; }
}

public class DemoEnum3 {
   public static void main(String args[])
   {
      Kota kt;
 
      // Menampilkan banyak penduduk Medan.
      System.out.println("Medan memiliki " +
         Kota.Medan.getPenduduk() +
         " juta penduduk.\n");
 
      // Menampilkan semua kota dan penduduknya.
      System.out.println("Semua penduduk kota:");
      for(Kota a : Kota.values())
         System.out.println(a + " memiliki " + a.getPenduduk() +
            " juta penduduk.");
   }
}

Ketika dijalankan, program ini menghasilkan keluaran berikut:

Medan memiliki 5 juta penduduk.

Semua penduduk kota:
Malang memiliki 3 juta penduduk.
Medan memiliki 5 juta penduduk.
Jakarta memiliki 15 juta penduduk.
Jogja memiliki 7 juta penduduk.
Bandung memiliki 9 juta penduduk.

Versi program ini menambahkan tiga hal. Pertama adalah variabel enumerasi penduduk, yang dipakai untuk menampung jumlah penduduk dari tiap kota. Kedua adalah konstruktor Kota, yang memiliki satu parameter, yaitu jumlah penduduk. Ketiga adalah metode getPenduduk(), yang menghasilkan nilai dari penduduk.

Ketika variabel kt dideklarasikan di dalam main(), konstruktor untuk Kota akan dipanggil sekali untuk setiap konstanta yang ditetapkan. Perhatikan bagaimana argumen kepada konstruktor diberikan, dengan menempatkannya di dalam kurung pada tiap konstanta, seperti ditunjukkan di sini:

Malang(3), Medan(5), Jakarta(15), Jogja(7), Bandung(9);

Nilai-nilai ini dilewatkan kepada parameter p dari Kotak(), yang kemudian menugaskan nilai ini kepada penduduk. Jadi, konstruktor dipanggil untuk tiap konstanta tersebut.

Karena tiap konstanta enumerasi memiliki salinan sendiri atas penduduk, Anda bisa memperoleh nilai penduduk dengan memanggil getPenduduk(). Sebagai contoh, pada main(), jumlah penduduk dari Medan didapatkan dengan memanggil berikut:

Kota.Medan.getPenduduk()

Penduduk dari tiap kota didapatkan dengan membaca setiap konstanta enumerasi menggunakan loop for. Karena ada salinan dari penduduk untuk tiap konstanta enumerasi, nilai yang berkaitan dengan konstanta satu terpisah dan berbeda dari nilai yang berkaitan dengan konstanta lain. Ini merupakan konsep yang hebat, yang bisa tersedia ketika enumerasi diimplementasikan sebagai kelas, seperti yang dilakukan Java.

Meskipun contoh tersebut memuat hanya satu konstruktor, sebuah enum dapat memberikan dua atau lebih konstruktor terbeban, seperti kelas biasa. Sebagai contoh, versi program ini menyediakan satu konstruktor default yang menginisialisasi penduduk menjadi bernilai -1 untuk mengindikasikan bahwa tidak ada data penduduk yang tersedia:

// Sebuah enumerasi yang memuat nama-nama kota di Indonesia.
enum Kota {
   Malang(3), Medan(5), Jakarta, Jogja(7), Bandung(9);

   private int penduduk; // banyak penduduk

   // Konstruktor
   Kota(int p) {penduduk = p; }

   // Konstruktor default
   Kota() { penduduk = -1; }
    
   // Metode
   int getPenduduk() { return penduduk; }
}

Perhatikan bahwa pada versi ini, Jakarta tidak diberikan argumen. Ini berarti bahwa konstruktor default akan dipanggil, dan variabel penduduk dari Jakarta akan diberikan nilai -1. Berikut adalah program utuh dari versi program ini:

// Menggunakan konstruktor, variabel, dan metode dari enumerasi.

// Sebuah enumerasi yang memuat nama-nama kota di Indonesia.
enum Kota {
   Malang(3), Medan(5), Jakarta, Jogja(7), Bandung(9);

   private int penduduk; // banyak penduduk

 // Konstruktor
   Kota(int p) {penduduk = p; }
   
   // Konstruktor default
   Kota() { penduduk = -1; }
    
   // Metode
   int getPenduduk() { return penduduk; }
}

public class DemoEnum3 {
   public static void main(String args[])
   {
      Kota kt;
 
      // Menampilkan banyak penduduk Medan.
      System.out.println("Medan memiliki " +
         Kota.Medan.getPenduduk() +
         " juta penduduk.\n");
 
      // Menampilkan semua kota dan penduduknya.
      System.out.println("Semua penduduk kota:");
      for(Kota a : Kota.values())
         System.out.println(a + " memiliki " + a.getPenduduk() +
            " juta penduduk.");
   }
}

Program di atas menghasilkan keluaran berikut:

Medan memiliki 5 juta penduduk.

Semua penduduk kota:
Malang memiliki 3 juta penduduk.
Medan memiliki 5 juta penduduk.
Jakarta memiliki -1 juta penduduk.
Jogja memiliki 7 juta penduduk.
Bandung memiliki 9 juta penduduk.

Ada dua pembatasan yang berlaku pada enumerasi. Pertama enumerasi tidak dapat mewarisi kelas lain. Kedua, sebuah enum tidak bisa menjadi superkelas. Ini berarti bahwa enum tidak bisa diwarisi. Selain itu, enum berperilaku mirip seperti kelas biasa. Hal kunci yang perlu diingat adalah bahwa tiap konstanta enumerasi adalah sebuah objek kelas dari enumerasi yang mendefinisikannya.


Enumerasi Mewarisi Enum
Meskipun Anda tidak bisa mewarisi superkelas ketika mendeklarasikan sebuah enum, semua enumerasi secara otomatis mewarisi satu: java.lang.Enum. Kelas ini mendefinisikan sejumlah metode yang tersedia untuk semua enumerasi.

Anda bisa memperoleh sebuah nilai yang diindikasikan oleh posisi dari sebuah konstanta enumerasi pada daftar konstanta yang ada. Nilai ini dikenal pula dengan nilai ordinal, dan diperoleh menggunakan metode ordinal(), seperti berikut:

final int ordinal()

Metode ini menghasilkan nilai ordinal dari konstanta pemanggil. Nilai ordinal diawali dari nol. Jadi, pada enumerasi Kota, Malang memiliki nilai ordinal nol, Medan memiliki nilai ordinal 1, dan seterusnya.


Selanjutnya  >>>



No comments: