1. Pengetikan

Variabel yang menyimpan tipe referensi (kelas) juga dapat dikonversi ke tipe yang berbeda. Tapi ini hanya berfungsi dalam hierarki tipe tunggal. Mari kita lihat contoh sederhana. Misalkan kita memiliki hierarki kelas berikut, di mana kelas di bawah mewarisi kelas di atas.

Pengetikan

Typecasting dari tipe referensi serta yang primitif juga dikategorikan sebagai pelebaran dan penyempitan.

Kita melihat bahwa class Cat mewarisi class Pet, dan class Pet, pada gilirannya, mewarisi class Animal.

Jika kita menulis kode seperti ini:

Animal kitten = new Cat();

Ini adalah konversi tipe pelebaran . Ini juga disebut pemeran implisit. Kita telah memperluas referensi cat sehingga sekarang merujuk ke objek Cat . Dengan konversi tipe seperti ini, kita tidak akan dapat menggunakan referensi anak kucing untuk memanggil metode yang ada di kelas Cat tetapi tidak ada di kelas Hewan .

Konversi penyempitan (atau pemeran eksplisit) terjadi dalam arah yang berlawanan:

Cat cat = (Cat) kitten;

Kami secara eksplisit menunjukkan bahwa kami ingin mentransmisikan referensi yang disimpan dalam variabel anak kucing (yang bertipe Animal ) ke tipe Cat .



2. Memeriksa jenis suatu objek

Tetapi Anda harus sangat berhati-hati di sini. Jika kamu melakukan ini:

Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;

Kompiler akan mengizinkan kode ini, tetapi akan ada kesalahan saat program dijalankan! JVM akan mengeluarkan pengecualian:

Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf

Referensi ke objek Cat hanya dapat disimpan dalam variabel yang tipenya merupakan leluhur dari kelas Cat: Pet, Animal, atau Object.

Mengapa demikian?

Poin yang relevan di sini adalah bahwa referensi objek digunakan untuk merujuk ke metode dan variabel dari objek tersebut . Dan tidak akan ada masalah jika kita menggunakan variabel Hewan untuk menyimpan referensi ke objek Cat: tipe Cat selalu memiliki variabel dan metode dari tipe Hewan — ia mewarisinya!

Tetapi jika JVM mengizinkan kita untuk menyimpan referensi ke objek Cat dalam variabel Wolf, maka kita mungkin mengalami situasi di mana kita mungkin mencoba menggunakan variabel grayWolf untuk memanggil metode yang tidak ada dalam objek Cat yang disimpan dalam variabel itu . Itu sebabnya pengaturan ini tidak diperbolehkan.

Java memiliki operator khusus instanceofyang memungkinkan Anda memeriksa apakah suatu objek bertipe tertentu dan karenanya dapat disimpan ke dalam variabel bertipe tertentu. Ini terlihat cukup sederhana:

variable instanceof Type

Contoh:

Animal beast = new Cat();
if (beast instanceof Wolf)
{
   Wolf grayWolf = (Wolf) beast;
}

Kode ini tidak akan menyebabkan kesalahan — bahkan saat runtime.

Berikut adalah beberapa contoh yang menggambarkan situasi:

Konversi tipe pelebaran Keterangan
Cow cow = new Whale();

Ini adalah konversi pelebaran klasik — tidak diperlukan operator konversi jenis. Sekarang hanya metode yang didefinisikan dalam Cowkelas yang dapat dipanggil pada Whaleobjek.

Pada cowvariabel , kompiler hanya akan membiarkan Anda memanggil metode yang Cowdimiliki tipenya (kelas).

Konversi tipe penyempitan
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Konversi penyempitan klasik: Anda perlu menambahkan pemeriksaan jenis dan operator transmisi.
Variabel Cow cowmenyimpan referensi ke Whaleobjek.
Kami memverifikasi bahwa ini masalahnya , dan kemudian melakukan konversi jenis (penyempitan). Atau biasa juga disebut :
tipe pemeran
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
Anda dapat mempersempit tipe referensi tanpa memeriksa tipe objek.
Jika cowvariabel merujuk ke objek yang bukan a Whale, maka InvalidClassCastExceptionakan dihasilkan.


3. Memanggil metode asli: superkata kunci

Saat mengganti metode kelas induk, kadang-kadang alih-alih menggantinya dengan milik kita sendiri, kita hanya ingin menambahkannya sedikit.

Akan keren jika kita dapat menggunakan metode kelas induk dalam metode kita, lalu mengeksekusi beberapa kode kita sendiri. Atau mungkin pertama-tama jalankan kode kita sendiri, lalu panggil metode kelas induk.

Dan Java memungkinkan kita melakukan hal itu. Untuk memanggil metode kelas induk, lakukan ini:

super.method(arguments);

Contoh:

class PeaceTime
{
   public double getPi()
   {
      return 3.14;
   }
}

class WarTime extends PeaceTime
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

Di masa perang, nilainya Pibisa lebih besar dari 6! Tentu saja, kami bercanda, tetapi contoh ini menunjukkan bagaimana semua ini bisa berhasil.

Berikut adalah beberapa contoh lagi untuk memperjelas beberapa hal:

Kode Keterangan
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.print("This is incorrect: ");
      super.printName();
      System.out.println("I'm a whale");
   }
}
Cowdan Whalekelas
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
Output layar akan menjadi:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

Ini adalah hal yang sulit. Sejujurnya, ini salah satu hal tersulit di OOP . Yang mengatakan, Anda memang perlu mengetahui dan memahaminya.