CodeGym/Blog Java/rawak/50 soalan dan jawapan temu duga kerja teratas untuk Java ...
John Squirrels
Tahap
San Francisco

50 soalan dan jawapan temu duga kerja teratas untuk Java Core. Bahagian 2

Diterbitkan dalam kumpulan
50 soalan dan jawapan temu duga kerja teratas untuk Java Core. Bahagian 150 soalan dan jawapan temu duga kerja teratas untuk Java Core.  Bahagian 2 - 1

Multithreading

24. Bagaimanakah cara untuk saya mencipta benang baharu dalam Java?

Satu cara atau yang lain, thread dicipta menggunakan kelas Thread. Tetapi terdapat pelbagai cara untuk melakukan ini…
  1. Warisi java.lang.Thread .
  2. Laksanakan antara muka java.lang.Runnable — pembina kelas Thread mengambil objek Runnable.
Mari kita bercakap tentang setiap daripada mereka.

Warisi kelas Thread

Dalam kes ini, kami menjadikan kelas kami mewarisi java.lang.Thread . Ia mempunyai kaedah run() , dan itulah yang kita perlukan. Semua kehidupan dan logik benang baru akan berada dalam kaedah ini. Ia seperti kaedah utama untuk benang baru. Selepas itu, yang tinggal hanyalah mencipta objek kelas kami dan memanggil kaedah mula() . Ini akan mencipta benang baharu dan mula melaksanakan logiknya. Mari kita lihat:
/**
* An example of how to create threads by inheriting the {@link Thread} class.
*/
class ThreadInheritance extends Thread {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance threadInheritance1 = new ThreadInheritance();
       ThreadInheritance threadInheritance2 = new ThreadInheritance();
       ThreadInheritance threadInheritance3 = new ThreadInheritance();
       threadInheritance1.start();
       threadInheritance2.start();
       threadInheritance3.start();
   }
}
Output konsol akan menjadi seperti ini:
Benang-1 Benang-0 Benang-2
Iaitu, walaupun di sini kita melihat bahawa utas dilaksanakan tidak mengikut urutan, tetapi sebaliknya seperti yang dilihat JVM sesuai untuk menjalankannya :)

Laksanakan antara muka Runnable

Jika anda menentang warisan dan/atau sudah mewarisi beberapa kelas lain, anda boleh menggunakan antara muka java.lang.Runnable . Di sini, kami membuat kelas kami melaksanakan antara muka ini dengan melaksanakan kaedah run() , seperti dalam contoh di atas. Yang tinggal hanyalah mencipta objek Thread . Nampaknya lebih banyak baris kod lebih teruk. Tetapi kita tahu betapa berbahayanya warisan dan lebih baik untuk mengelakkannya dengan segala cara ;) Lihatlah:
/**
* An example of how to create threads from the {@link Runnable} interface.
* It's easier than easy — we implement this interface and then pass an instance of our object
* to the constructor.
*/
class ThreadInheritance implements Runnable {

   @Override
   public void run() {
       System.out.println(Thread.currentThread().getName());
   }

   public static void main(String[] args) {
       ThreadInheritance runnable1 = new ThreadInheritance();
       ThreadInheritance runnable2 = new ThreadInheritance();
       ThreadInheritance runnable3 = new ThreadInheritance();

       Thread threadRunnable1 = new Thread(runnable1);
       Thread threadRunnable2 = new Thread(runnable2);
       Thread threadRunnable3 = new Thread(runnable3);

       threadRunnable1.start();
       threadRunnable2.start();
       threadRunnable3.start();
   }
}
Dan inilah hasilnya:
Benang-0 Benang-1 Benang-2

25. Apakah perbezaan antara proses dan benang?

50 soalan dan jawapan temu duga kerja teratas untuk Java Core.  Bahagian 2 - 2Proses dan utas adalah berbeza dalam cara berikut:
  1. Program yang sedang berjalan dipanggil proses, tetapi utas adalah sebahagian daripada proses.
  2. Proses adalah bebas, tetapi utas adalah kepingan proses.
  3. Proses mempunyai ruang alamat yang berbeza dalam ingatan, tetapi benang berkongsi ruang alamat yang sama.
  4. Pertukaran konteks antara utas adalah lebih pantas daripada bertukar antara proses.
  5. Komunikasi antara proses adalah lebih perlahan dan lebih mahal daripada komunikasi antara benang.
  6. Sebarang perubahan dalam proses induk tidak menjejaskan proses anak, tetapi perubahan dalam urutan induk boleh menjejaskan urutan anak.

26. Apakah faedah multithreading?

  1. Multithreading membolehkan aplikasi/program sentiasa responsif kepada input, walaupun ia sudah menjalankan beberapa tugas latar belakang;
  2. Multithreading memungkinkan untuk menyelesaikan tugas dengan lebih cepat, kerana benang berjalan secara bebas;
  3. Multithreading menyediakan penggunaan memori cache yang lebih baik, kerana benang boleh mengakses sumber memori yang dikongsi;
  4. Multithreading mengurangkan bilangan pelayan yang diperlukan, kerana satu pelayan boleh menjalankan berbilang thread secara serentak.

27. Apakah keadaan dalam kitaran hayat benang?

50 soalan dan jawapan temu duga kerja teratas untuk Java Core.  Bahagian 2 - 3
  1. Baharu: Dalam keadaan ini, objek Thread dibuat menggunakan operator baharu, tetapi utas baharu belum wujud lagi. Benang tidak bermula sehingga kita memanggil kaedah mula () .
  2. Runnable: Dalam keadaan ini, thread sedia untuk dijalankan selepas start() kaedah dipanggil. Walau bagaimanapun, ia belum lagi dipilih oleh penjadual benang.
  3. Berjalan: Dalam keadaan ini, penjadual benang memilih benang daripada keadaan sedia, dan ia berjalan.
  4. Menunggu/Disekat: dalam keadaan ini, benang tidak berjalan, tetapi ia masih hidup atau menunggu urutan lain selesai.
  5. Mati/Ditamatkan: apabila benang keluar daripada kaedah run() , ia berada dalam keadaan mati atau ditamatkan.

28. Adakah mungkin untuk menjalankan benang dua kali?

Tidak, kami tidak boleh memulakan semula utas, kerana selepas utas bermula dan berjalan, ia masuk ke keadaan Mati. Jika kita cuba memulakan benang dua kali, java.lang.IllegalThreadStateException akan dibuang. Mari kita lihat:
class DoubleStartThreadExample extends Thread {

   /**
    * Simulate the work of a thread
    */
   public void run() {
	// Something happens. At this state, this is not essential.
   }

   /**
    * Start the thread twice
    */
   public static void main(String[] args) {
       DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
       doubleStartThreadExample.start();
       doubleStartThreadExample.start();
   }
}
Akan ada pengecualian sebaik sahaja pelaksanaan datang ke permulaan kedua urutan yang sama. Cuba sendiri ;) Lebih baik melihat ini sekali daripada mendengarnya seratus kali.

29. Bagaimana jika anda memanggil run() terus tanpa memanggil start()?

Ya, anda pasti boleh memanggil kaedah run() , tetapi utas baharu tidak akan dibuat dan kaedah itu tidak akan dijalankan pada utas berasingan. Dalam kes ini, kita mempunyai objek biasa yang memanggil kaedah biasa. Jika kita bercakap tentang kaedah start() , maka itu perkara lain. Apabila kaedah ini dipanggil, JVM memulakan utas baharu. Benang ini, seterusnya, memanggil kaedah kami ;) Tidak percaya? Di sini, cubalah:
class ThreadCallRunExample extends Thread {

   public void run() {
       for (int i = 0; i < 5; i++) {
           System.out.print(i);
       }
   }

   public static void main(String args[]) {
       ThreadCallRunExample runExample1 = new ThreadCallRunExample();
       ThreadCallRunExample runExample2 = new ThreadCallRunExample();

       // Two ordinary methods will be called in the main thread, one after the other.
       runExample1.run();
       runExample2.run();
   }
}
Dan output konsol akan kelihatan seperti ini:
0123401234
Seperti yang anda lihat, tiada benang dibuat. Semuanya berfungsi seperti dalam kelas biasa. Pertama, kaedah objek pertama telah dilaksanakan, dan kemudian yang kedua.

30. Apakah benang daemon?

Benang daemon ialah benang yang melaksanakan tugas dengan keutamaan yang lebih rendah daripada benang lain. Dalam erti kata lain, tugasnya adalah untuk melaksanakan tugas tambahan yang perlu dilakukan hanya bersempena dengan utas (utama) yang lain. Terdapat banyak benang daemon yang berjalan secara automatik, seperti kutipan sampah, pemuktamad, dsb.

Mengapa Java menamatkan benang daemon?

Tujuan tunggal utas daemon adalah untuk menyediakan sokongan latar belakang kepada utas pengguna. Sehubungan itu, jika utas utama ditamatkan, maka JVM secara automatik menamatkan semua utas daemonnya.

Kaedah kelas Thread

Kelas java.lang.Thread menyediakan dua kaedah untuk bekerja dengan benang daemon:
  1. public void setDaemon(status boolean) — Kaedah ini menunjukkan sama ada ini akan menjadi benang daemon. Lalai adalah palsu . Ini bermakna tiada benang daemon akan dibuat melainkan anda menyatakannya secara khusus.
  2. public boolean isDaemon() — Kaedah ini pada asasnya adalah pengambil untuk pembolehubah daemon , yang kami tetapkan menggunakan kaedah sebelumnya.
Contoh:
class DaemonThreadExample extends Thread {

   public void run() {
       // Checks whether this thread is a daemon
       if (Thread.currentThread().isDaemon()) {
           System.out.println("daemon thread");
       } else {
           System.out.println("user thread");
       }
   }

   public static void main(String[] args) {
       DaemonThreadExample thread1 = new DaemonThreadExample();
       DaemonThreadExample thread2 = new DaemonThreadExample();
       DaemonThreadExample thread3 = new DaemonThreadExample();

       // Make thread1 a daemon thread.
       thread1.setDaemon(true);

       System.out.println("daemon? " + thread1.isDaemon());
       System.out.println("daemon? " + thread2.isDaemon());
       System.out.println("daemon? " + thread3.isDaemon());

       thread1.start();
       thread2.start();
       thread3.start();
   }
}
Output konsol:
daemon? daemon sebenar? daemon palsu? benang daemon palsu benang pengguna benang pengguna
Daripada output, kita melihat bahawa di dalam benang itu sendiri, kita boleh menggunakan kaedah statik currentThread() untuk mengetahui benang yang mana. Sebagai alternatif, jika kita mempunyai rujukan kepada objek benang, kita juga boleh mengetahui secara langsung daripadanya. Ini menyediakan tahap kebolehkonfigurasian yang diperlukan.

31. Adakah mungkin untuk menjadikan benang sebagai daemon selepas ia dicipta?

Tidak. Jika anda cuba melakukan ini, anda akan mendapat IllegalThreadStateException . Ini bermakna kita hanya boleh mencipta benang daemon sebelum ia bermula. Contoh:
class SetDaemonAfterStartExample extends Thread {

   public void run() {
       System.out.println("Working...");
   }

   public static void main(String[] args) {
       SetDaemonAfterStartExample afterStartExample = new SetDaemonAfterStartExample();
       afterStartExample.start();

       // An exception will be thrown here
       afterStartExample.setDaemon(true);
   }
}
Output konsol:
Berfungsi... Pengecualian dalam utas "utama" java.lang.IllegalThreadStateException di java.lang.Thread.setDaemon(Thread.java:1359) di SetDaemonAfterStartExample.main(SetDaemonAfterStartExample.java:14)

32. Apakah cangkuk penutupan?

Cangkuk penutupan ialah utas yang dipanggil secara tersirat sebelum mesin maya Java (JVM) dimatikan. Oleh itu, kita boleh menggunakannya untuk melepaskan sumber atau menyimpan keadaan apabila mesin maya Java dimatikan secara normal atau tidak normal. Kita boleh menambah cangkuk penutupan menggunakan kaedah berikut:
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
Seperti yang ditunjukkan dalam contoh:
/**
* A program that shows how to start a shutdown hook thread,
* which will be executed right before the JVM shuts down
*/
class ShutdownHookThreadExample extends Thread {

   public void run() {
       System.out.println("shutdown hook executed");
   }

   public static void main(String[] args) {

       Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());

       System.out.println("Now the program is going to fall asleep. Press Ctrl+C to terminate it.");
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}
Output konsol:
Sekarang program akan tertidur. Tekan Ctrl+C untuk menamatkannya. cangkuk penutupan dilaksanakan

33. Apakah penyegerakan?

Di Java, penyegerakan ialah keupayaan untuk mengawal akses berbilang benang kepada mana-mana sumber yang dikongsi. Apabila beberapa utas cuba melaksanakan tugas yang sama secara serentak, anda boleh mendapat hasil yang salah. Untuk menyelesaikan masalah ini, Java menggunakan penyegerakan, yang membenarkan hanya satu utas dijalankan pada satu masa. Penyegerakan boleh dicapai dalam tiga cara:
  • Menyegerakkan kaedah
  • Menyegerakkan blok tertentu
  • Penyegerakan statik

Menyegerakkan kaedah

Kaedah yang disegerakkan digunakan untuk mengunci objek untuk sebarang sumber yang dikongsi. Apabila benang memanggil kaedah yang disegerakkan, ia secara automatik memperoleh kunci objek dan melepaskannya apabila benang menyelesaikan tugasnya. Untuk membuat ini berfungsi, anda perlu menambah kata kunci yang disegerakkan . Kita boleh melihat bagaimana ini berfungsi dengan melihat contoh:
/**
* An example where we synchronize a method. That is, we add the synchronized keyword to it.
* There are two authors who want to use one printer. Each of them has composed their own poems
* And of course they don’t want their poems mixed up. Instead, they want work to be performed in * * * order for each of them
*/
class Printer {

   synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {
       // One object for two threads
       Printer printer  = new Printer();

       // Create two threads
       Writer1 writer1 = new Writer1(printer);
       Writer2 writer2 = new Writer2(printer);

       // Start them
       writer1.start();
       writer2.start();
   }
}

/**
* Author No. 1, who writes an original poem.
*/
class Writer1 extends Thread {
   Printer printer;

   Writer1(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<string> poem = Arrays.asList("I ", this.getName(), " Write", " A Letter");
       printer.print(poem);
   }

}

/**
* Author No. 2, who writes an original poem.
*/
class Writer2 extends Thread {
   Printer printer;

   Writer2(Printer printer) {
       this.printer = printer;
   }

   public void run() {
       List<String> poem = Arrays.asList("I Do Not ", this.getName(), " Not Write", " No Letter");
       printer.print(poem);
   }
}
Dan output konsol adalah ini:
Saya Thread-0 Tulis Surat Saya Tidak Thread-1 Bukan Tulis Tiada Surat

Blok penyegerakan

Blok disegerakkan boleh digunakan untuk melakukan penyegerakan pada mana-mana sumber tertentu dalam kaedah. Katakan bahawa dalam kaedah yang besar (ya, anda tidak sepatutnya menulisnya, tetapi kadangkala ia berlaku) anda perlu menyegerakkan hanya bahagian kecil atas sebab tertentu. Jika anda meletakkan semua kod kaedah dalam blok disegerakkan, ia akan berfungsi sama seperti kaedah disegerakkan. Sintaks kelihatan seperti ini:
synchronized ("object to be locked") {
   // The code that must be protected
}
Untuk mengelak daripada mengulangi contoh sebelumnya, kami akan mencipta benang menggunakan kelas tanpa nama, iaitu kami akan segera melaksanakan antara muka Runnable.
/**
* This is how a synchronization block is added.
* Inside the block, you need to specify which object's mutex will be acquired.
*/
class Printer {

   void print(List<String> wordsToPrint) {
       synchronized (this) {
           wordsToPrint.forEach(System.out::print);
       }
       System.out.println();
   }

   public static void main(String args[]) {
       // One object for two threads
       Printer printer = new Printer();

       // Create two threads
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I ", "Writer1", " Write", " A Letter");
               printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I Do Not ", "Writer2", " Not Write", " No Letter");
               printer.print(poem);
           }
       });

       // Start them
       writer1.start();
       writer2.start();
   }
}

}
Dan output konsol adalah ini:
Saya Penulis1 Tulis Surat Saya Tidak Penulis2 Tidak Tulis Tiada Surat

Penyegerakan statik

Jika anda membuat kaedah statik disegerakkan, maka penguncian akan berlaku pada kelas, bukan objek. Dalam contoh ini, kami melakukan penyegerakan statik dengan menggunakan kata kunci disegerakkan kepada kaedah statik:
/**
* This is how a synchronization block is added.
* Inside the block, you need to specify which object's mutex will be acquired.
*/
class Printer {

   static synchronized void print(List<String> wordsToPrint) {
       wordsToPrint.forEach(System.out::print);
       System.out.println();
   }

   public static void main(String args[]) {

       // Create two threads
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I ", "Writer1", " Write", " A Letter");
               Printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("I Do Not ", "Writer2", " Not Write", " No Letter");
               Printer.print(poem);
           }
       });

       // Start them
       writer1.start();
       writer2.start();
   }
}
Dan output konsol adalah ini:
Saya Tidak Penulis2 Tidak Menulis Tiada Surat Saya Penulis1 Menulis Surat

34. Apakah pembolehubah yang tidak menentu?

Dalam pengaturcaraan berbilang benang, kata kunci yang tidak menentu digunakan untuk keselamatan benang. Apabila pembolehubah boleh ubah diubah suai, perubahan itu kelihatan kepada semua utas lain, jadi pembolehubah boleh digunakan oleh satu utas pada satu masa. Dengan menggunakan kata kunci yang tidak menentu , anda boleh menjamin bahawa pembolehubah adalah selamat untuk benang dan disimpan dalam memori kongsi dan bahawa benang tidak akan menyimpannya dalam cache mereka. Apakah rupa ini?
private volatile AtomicInteger count;
Kami hanya menambah tidak menentu kepada pembolehubah. Tetapi perlu diingat bahawa ini tidak bermakna keselamatan benang lengkap... Lagipun, operasi pada pembolehubah mungkin bukan atom. Yang berkata, anda boleh menggunakan kelas Atom yang melakukan operasi secara atom, iaitu dalam satu arahan CPU. Terdapat banyak kelas sedemikian dalam pakej java.util.concurrent.atomic .

35. Apakah kebuntuan?

Di Jawa, kebuntuan adalah sesuatu yang boleh berlaku sebagai sebahagian daripada multithreading. Kebuntuan boleh berlaku apabila utas sedang menunggu kunci objek yang diperolehi oleh utas lain, dan utas kedua sedang menunggu kunci objek yang diperolehi oleh utas pertama. Ini bermakna kedua-dua utas sedang menunggu antara satu sama lain, dan pelaksanaan kod mereka tidak dapat diteruskan. 50 soalan dan jawapan temu duga kerja teratas untuk Java Core.  Bahagian 2 - 4Mari kita pertimbangkan contoh yang mempunyai kelas yang melaksanakan Runnable. Pembinanya mengambil dua sumber. Kaedah run() memperoleh kunci untuk mereka mengikut urutan. Jika anda mencipta dua objek kelas ini, dan menghantar sumber dalam susunan yang berbeza, maka anda boleh menemui jalan buntu dengan mudah:
class DeadLock {

   public static void main(String[] args) {
       final Integer r1 = 10;
       final Integer r2 = 15;

       DeadlockThread threadR1R2 = new DeadlockThread(r1, r2);
       DeadlockThread threadR2R1 = new DeadlockThread(r2, r1);

       new Thread(threadR1R2).start();
       new Thread(threadR2R1).start();
   }
}

/**
* A class that accepts two resources.
*/
class DeadlockThread implements Runnable {

   private final Integer r1;
   private final Integer r2;

   public DeadlockThread(Integer r1, Integer r2) {
       this.r1 = r1;
       this.r2 = r2;
   }

   @Override
   public void run() {
       synchronized (r1) {
           System.out.println(Thread.currentThread().getName() + " acquired resource: " + r1);

           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }

           synchronized (r2) {
               System.out.println(Thread.currentThread().getName() + " acquired resource: " + r2);
           }
       }
   }
}
Output konsol:
Benang pertama memperoleh sumber pertama Benang kedua memperoleh sumber kedua

36. Bagaimanakah anda mengelakkan kebuntuan?

Kerana kita tahu bagaimana kebuntuan berlaku, kita boleh membuat beberapa kesimpulan...
  • Dalam contoh di atas, kebuntuan berlaku disebabkan oleh fakta bahawa kita telah mengunci bersarang. Iaitu, kita mempunyai blok yang disegerakkan di dalam blok yang disegerakkan. Untuk mengelakkan ini, bukannya bersarang, anda perlu mencipta lapisan abstraksi yang lebih tinggi baharu, mengalihkan penyegerakan ke tahap yang lebih tinggi dan menghapuskan penguncian bersarang.
  • Semakin banyak penguncian yang anda lakukan, semakin besar kemungkinan akan berlaku kebuntuan. Oleh itu, setiap kali anda menambah blok disegerakkan, anda perlu memikirkan sama ada anda benar-benar memerlukannya dan sama ada anda boleh mengelak daripada menambah blok baharu.
  • Menggunakan Thread.join() . Anda juga boleh mengalami kebuntuan sementara satu utas menunggu yang lain. Untuk mengelakkan masalah ini, anda mungkin mempertimbangkan untuk menetapkan tamat masa untuk kaedah join() .
  • Jika kita mempunyai satu utas, maka tidak akan ada kebuntuan ;)

37. Apakah syarat perlumbaan?

Jika perlumbaan dalam kehidupan sebenar melibatkan kereta, maka perlumbaan dalam multithreading melibatkan benang. Tapi kenapa? :/ Terdapat dua utas yang sedang berjalan dan boleh mengakses objek yang sama. Dan mereka mungkin cuba mengemas kini keadaan objek kongsi pada masa yang sama. Semuanya jelas setakat ini, bukan? Benang dilaksanakan sama ada secara literal secara selari (jika pemproses mempunyai lebih daripada satu teras) atau secara berurutan, dengan pemproses memperuntukkan kepingan masa berselang. Kami tidak boleh menguruskan proses ini. Ini bermakna apabila satu utas membaca data daripada objek, kami tidak dapat menjamin bahawa ia akan mempunyai masa untuk menukar objek SEBELUM beberapa utas lain berbuat demikian. Masalah sedemikian timbul apabila kita mempunyai kombo "semak dan bertindak" ini. Apakah maksudnya? Katakan kita mempunyai pernyataan if yang badannya mengubah keadaan if itu sendiri, sebagai contoh:
int z = 0;

// Check
if (z < 5) {
// Act
   z = z + 5;
}
Dua utas boleh memasukkan blok kod ini secara serentak apabila z masih sifar dan kemudian kedua-dua utas boleh menukar nilainya. Akibatnya, kami tidak akan mendapat nilai yang dijangkakan sebanyak 5. Sebaliknya, kami akan mendapat 10. Bagaimanakah anda mengelakkan perkara ini? Anda perlu mendapatkan kunci sebelum menyemak dan bertindak, dan kemudian lepaskan kunci itu selepas itu. Iaitu, anda perlu meminta utas pertama memasuki blok if , lakukan semua tindakan, tukar z , dan hanya kemudian beri peluang pada utas seterusnya untuk melakukan perkara yang sama. Tetapi urutan seterusnya tidak akan memasuki blok if , kerana z kini akan menjadi 5:
// Acquire the lock for z
if (z < 5) {
   z = z + 5;
}
// Release z's lock
===================================================

Daripada kesimpulan

Saya ingin mengucapkan terima kasih kepada semua yang membaca hingga habis. Perjalanan itu jauh, tetapi anda bertahan! Mungkin tidak semuanya jelas. Ini adalah biasa. Apabila saya mula belajar Java, saya tidak dapat membungkus otak saya tentang apa itu pembolehubah statik. Tetapi bukan masalah besar. Saya tidur di atasnya, membaca beberapa sumber lagi, dan kemudian pemahaman itu datang. Persediaan untuk temu duga adalah lebih kepada soalan akademik dan bukannya praktikal. Akibatnya, sebelum setiap temu duga, anda harus menyemak dan menyegarkan semula dalam ingatan anda perkara-perkara yang mungkin anda jarang gunakan.

Dan seperti biasa, berikut adalah beberapa pautan berguna:

Terima kasih semua kerana sudi membaca. Jumpa lagi :) Profil GitHub saya50 soalan dan jawapan temu duga kerja teratas untuk Java Core.  Bahagian 2 - 5
Komen
  • Popular
  • Baru
  • Tua
Anda mesti log masuk untuk meninggalkan ulasan
Halaman ini tidak mempunyai sebarang ulasan lagi