CodeGym /Blog Java /rawak /Kelas tanpa nama
John Squirrels
Tahap
San Francisco

Kelas tanpa nama

Diterbitkan dalam kumpulan
Hai! Dalam pelajaran hari ini, kita akan terus mengkaji topik kelas bersarang. Kini tiba masanya untuk kumpulan terakhir: kelas dalaman tanpa nama. Mari kembali ke rajah kami: Kelas tanpa nama - 2Seperti kelas tempatan yang kita bincangkan dalam pelajaran lepas, kelas tanpa nama adalah sejenis kelas dalaman... Mereka juga mempunyai beberapa persamaan dan perbezaan. Tetapi pertama-tama, mari kita selami: mengapa sebenarnya mereka dipanggil "tanpa nama"? Untuk menjawabnya, pertimbangkan contoh mudah. Bayangkan kita mempunyai program asas yang sentiasa berjalan dan melakukan sesuatu. Kami ingin mewujudkan sistem pemantauan untuk program ini, yang terdiri daripada beberapa modul. Satu modul akan menjejaki petunjuk umum prestasi dan mengekalkan log. Yang kedua akan mendaftar dan merekodkan ralat dalam log ralat. Yang ketiga akan menjejaki aktiviti yang mencurigakan: contohnya, percubaan akses tanpa kebenaran dan perkara lain yang berkaitan dengan keselamatan. Kerana ketiga-tiga modul sepatutnya, pada dasarnya, hanya bermula pada permulaan program dan berjalan di latar belakang,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 kelas konkrit akan melaksanakannya:

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
Nampaknya semuanya teratur. Kami mempunyai sistem yang cukup koheren yang terdiri daripada beberapa modul. Setiap daripada mereka mempunyai perangai sendiri. Jika kita memerlukan modul baru, kita boleh menambahnya, kerana kita mempunyai antara muka yang agak mudah untuk dilaksanakan. Tetapi mari kita fikirkan bagaimana sistem pemantauan kita akan berfungsi. Kelas tanpa nama - 3Pada asasnya, kita hanya perlu mencipta 3 objek — GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule— dan memanggil startMonitoring()kaedah pada setiap satu daripadanya. Iaitu, apa yang perlu kita lakukan ialah mencipta 3 objek dan memanggil 1 kaedah padanya.

public class Main {

   public static void main(String[] args) {

       GeneralIndicatorMonitoringModule generalModule = new GeneralIndicatorMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Output konsol:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Dan dengan kerja yang sedikit itu, kami telah menulis keseluruhan sistem: 3 kelas dan satu antara muka! Dan semua ini untuk mencapai 6 baris kod. Sebaliknya, apakah pilihan kita? Nah, tidaklah hebat kami menulis kelas "sekali" ini. Tetapi bagaimana kita boleh membetulkannya? Di sini kelas dalaman tanpa nama datang untuk menyelamatkan kami! Inilah rupa mereka dalam kes kami:

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Mari kita fikirkan apa yang berlaku! Nampaknya kami sedang mencipta objek antara muka:

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
Tetapi kami telah lama mengetahui bahawa kami tidak boleh mencipta objek antara muka! Dan begitulah - ia adalah mustahil. Sebenarnya, bukan itu yang kita lakukan. Apabila kita menulis:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
perkara berikut berlaku di dalam mesin Java:
  1. Kelas Java yang tidak dinamakan dicipta yang melaksanakan MonitoringSystemantara muka.
  2. Apabila pengkompil melihat kelas sedemikian, ia memerlukan anda untuk melaksanakan semua kaedah antara muka MonitoringSystem(kami melakukan ini 3 kali).
  3. Satu objek kelas ini dicipta. Beri perhatian kepada kod:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Terdapat koma bertitik di hujungnya! Ada sebabnya. Kami mengisytiharkan kelas secara serentak (menggunakan pendakap kerinting) dan mencipta contoh kelas itu (menggunakan ();). Setiap daripada tiga objek kami mengatasi startMonitoring()kaedah dengan cara tersendiri. Akhirnya, kami hanya memanggil kaedah ini pada setiap daripada mereka:

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Output konsol:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Itu sahaja! Kami mencapai objektif kami: kami mencipta tiga MonitoringSystemobjek, mengatasi kaedah dalam tiga cara berbeza, dan memanggilnya tiga kali. Ketiga-tiga modul telah berjaya dipanggil dan sedang berjalan. Pada masa yang sama, struktur program kami menjadi lebih mudah! Lagipun, kelas GeneralIndicatorMonitoringModule, ErrorMonitoringModule, dan SecurityModulekini boleh dialih keluar sepenuhnya daripada program! Kami tidak memerlukan mereka — kami melakukan kerja yang hebat tanpa mereka. Jika setiap kelas tanpa nama kami memerlukan beberapa gelagat yang berbeza, contohnya kaedah khusus tersendiri yang tidak dimiliki oleh kelas lain, kami boleh menambahkannya dengan mudah:

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
Dokumentasi Oracle memberikan cadangan yang baik : "Gunakan [kelas tanpa nama] jika anda perlu menggunakan kelas tempatan sekali sahaja." Kelas tanpa nama ialah kelas dalaman yang lengkap. Sehubungan itu, ia mempunyai akses kepada pembolehubah kelas luaran, termasuk pembolehubah statik dan peribadi:

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
Mereka mempunyai persamaan dengan kelas tempatan: mereka boleh dilihat hanya dalam kaedah di mana ia diisytiharkan. Dalam contoh di atas, sebarang percubaan untuk mengakses errorModuleobjek di luar main()kaedah akan gagal. Dan terdapat satu lagi batasan penting yang diwarisi oleh kelas tanpa nama daripada "nenek moyang" mereka (kelas dalam): kelas tanpa nama tidak boleh mengandungi pembolehubah dan kaedah statik . Dalam contoh di atas, jika kita cuba membuat getCurrentErrorCount()kaedah statik, pengkompil akan menghasilkan ralat:

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
Kami mendapat hasil yang sama jika kami cuba mengisytiharkan pembolehubah statik:

MonitoringSystem errorModule = new MonitoringSystem() {

   // Error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
Dan pelajaran kita hari ini telah berakhir! Tetapi walaupun kami telah menyiasat kumpulan terakhir kelas bersarang, kami masih belum menyelesaikan topik ini. Apa lagi yang akan kita pelajari tentang kelas bersarang? Anda pasti akan mengetahuinya tidak lama lagi! :)
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION