JavaRush /Java Blog /Random-ID /50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas. Ba...

50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas. Bagian 3

Dipublikasikan di grup Random-ID
50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas. Bagian 1 50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas. Bagian 2

Multithread

37. Bagaimana cara membuat thread (aliran) baru di Java?

Dengan satu atau lain cara, pembuatan terjadi melalui penggunaan kelas Thread. Tapi mungkin ada pilihan di sini...
  1. Kami mewarisi darijava.lang.Thread
  2. Kami mengimplementasikan antarmuka yang objeknya menerima kelas java.lang.RunnablekonstruktorThread
Mari kita bicara tentang masing-masingnya.

Kami mewarisi dari kelas Thread

Untuk membuat ini berhasil, di kelas kami, kami mewarisi java.lang.Thread. Ini mengandung sabu run(), itulah yang kita butuhkan. Seluruh kehidupan dan logika thread baru akan ada dalam metode ini. Ini adalah semacam mainmetode untuk thread baru. Setelah ini, yang tersisa hanyalah membuat objek kelas kita dan menjalankan metodenya start(), yang akan membuat thread baru dan menjalankan logika yang tertulis di dalamnya. Mari lihat:
/**
* Пример того, How создавать треды путем наследования {@link Thread} класса.
*/
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 ke konsol akan seperti ini:

Thread-1
Thread-0
Thread-2
Artinya, bahkan di sini kita melihat bahwa utas dieksekusi tidak secara bergantian, tetapi seperti yang diputuskan oleh JVM)

Menerapkan antarmuka Runnable

Jika Anda menentang pewarisan dan/atau sudah mewarisi salah satu kelas lain, Anda dapat menggunakan metode java.lang.Runnable. Di sini, di kelas kami, kami mengimplementasikan antarmuka ini dan mengimplementasikan metodenya run(), seperti pada contoh itu. Anda hanya perlu membuat lebih banyak objek Thread. Tampaknya semakin banyak garis semakin buruk. Tapi kita tahu betapa berbahayanya warisan dan lebih baik menghindarinya dengan segala cara ;) Mari kita lihat:
/**
* Пример того, How создавать треды из интерфейса {@link Runnable}.
* Здесь проще простого - реализуем этот интерфейс и потом передаем в конструктор
* экземпляр реализуемого an object.
*/
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 hasil eksekusinya:

Thread-0
Thread-1
Thread-2

38. Apa perbedaan antara proses dan thread?

50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas.  Bagian 3 - 1Ada perbedaan berikut antara proses dan thread:
  1. Suatu program yang sedang dieksekusi disebut proses, sedangkan Thread adalah bagian dari suatu proses.
  2. Proses bersifat independen, sedangkan thread adalah bagian dari suatu proses.
  3. Proses memiliki ruang alamat berbeda di memori, sedangkan thread berisi ruang alamat umum.
  4. Peralihan konteks antar thread lebih cepat dibandingkan dengan proses.
  5. Komunikasi antarproses lebih lambat dan lebih mahal daripada komunikasi antarthread.
  6. Setiap perubahan pada proses induk tidak mempengaruhi proses anak, sedangkan perubahan pada thread induk dapat mempengaruhi thread anak.

39. Apa kelebihan multithreading?

50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas.  Bagian 3 - 2
  1. Multithreading memungkinkan aplikasi/program untuk selalu merespons input meskipun sudah menjalankan beberapa tugas latar belakang;
  2. Multithreading memungkinkan Anda menyelesaikan tugas lebih cepat karena thread dijalankan secara independen;
  3. Multithreading memberikan pemanfaatan cache yang lebih baik karena thread berbagi sumber daya memori yang sama;
  4. Multithreading mengurangi jumlah server yang dibutuhkan karena satu server dapat menjalankan beberapa thread secara bersamaan.

40. Apa sajakah keadaan dalam siklus hidup sebuah thread?

50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas.  Bagian 3 - 3
  1. Baru: Dalam keadaan ini, objek kelas Threaddibuat menggunakan operator baru, tetapi threadnya tidak ada. Utas tidak dimulai sampai kita memanggil start().
  2. Dapat dijalankan: Dalam keadaan ini, thread siap dijalankan setelah memanggil metode awal(). Namun, ini belum dipilih oleh penjadwal thread.
  3. Berjalan: Dalam keadaan ini, penjadwal thread memilih thread dari keadaan siap dan berjalan.
  4. Waiting/Blocked : Dalam keadaan ini, thread tidak berjalan namun masih hidup atau menunggu thread lain selesai.
  5. Mati/Diakhiri: Ketika metode keluar, run()thread berada dalam keadaan dihentikan atau mati.

41. Apakah mungkin untuk memulai thread dua kali?

Tidak, kami tidak dapat memulai ulang thread karena setelah thread dimulai dan dijalankan, thread tersebut masuk ke status Mati. Jadi jika kita mencoba menjalankan thread dua kali, maka akan muncul runtimeException " java.lang.IllegalThreadStateException ". Mari lihat:
class DoubleStartThreadExample extends Thread {

   /**
    * Имитируем работу треда
    */
   public void run() {
	// что-то происходит. Для нас не существенно на этом этапе
   }

   /**
    * Запускаем тред дважды
    */
   public static void main(String[] args) {
       DoubleStartThreadExample doubleStartThreadExample = new DoubleStartThreadExample();
       doubleStartThreadExample.start();
       doubleStartThreadExample.start();
   }
}
Segera setelah pekerjaan mencapai awal kedua dari thread yang sama, maka akan ada pengecualian. Cobalah sendiri ;) lebih baik melihat sekali daripada mendengar seratus kali.

42. Bagaimana jika Anda memanggil metode run() secara langsung tanpa memanggil metode start()?

Ya, run()tentu saja Anda dapat memanggil suatu metode, tetapi ini tidak akan membuat thread baru dan mengeksekusinya sebagai thread terpisah. Dalam hal ini, ini adalah objek sederhana yang memanggil metode sederhana. Kalau kita bicara soal metode start(), lain lagi. Dengan meluncurkan metode ini, runtimeia meluncurkan metode baru dan, pada gilirannya, menjalankan metode kami ;) Jika Anda tidak percaya, cobalah:
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();

       // просто будут вызваны в потоке main два метода, один за другим.
       runExample1.run();
       runExample2.run();
   }
}
Dan output ke konsol akan menjadi seperti ini:

0123401234
Dapat dilihat bahwa tidak ada thread yang dibuat. Semuanya berjalan seperti kelas normal. Pertama, metode kelas pertama berhasil, lalu metode kedua.

43. Apa yang dimaksud dengan utas daemon?

50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas.  Bagian 3 - 4benang daemon (selanjutnya disebut thread daemon) adalah thread yang melakukan tugas di latar belakang sehubungan dengan thread lain. Artinya, tugasnya adalah melakukan tugas-tugas tambahan yang perlu dilakukan hanya bersamaan dengan thread (utama) lainnya. Ada banyak daemon thread yang bekerja secara otomatis, seperti Garbage Collector, finalizer, dll.

Mengapa Java menutup utas daemon?

Satu-satunya tujuan thread daemon adalah menyediakan layanan kepada thread pengguna untuk tugas dukungan latar belakang. Oleh karena itu, jika thread utama telah selesai, maka runtime secara otomatis menutup semua thread daemonnya.

Metode untuk bekerja di kelas Thread

Kelas ini java.lang.Threadmenyediakan dua metode untuk bekerja dengan daemon thread:
  1. public void setDaemon(boolean status)- menunjukkan bahwa ini akan menjadi thread daemon. Standarnya adalah false, yang berarti thread non-daemon akan dibuat kecuali ditentukan secara terpisah.
  2. public boolean isDaemon()- pada dasarnya ini adalah pengambil variabel daemonyang kita atur menggunakan metode sebelumnya.
Contoh:
class DaemonThreadExample extends Thread {

   public void run() {
       // Проверяет, демон ли этот поток or нет
       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();

       // теперь thread1 - поток-демон.
       thread1.setDaemon(true);

       System.out.println("демон?.. " + thread1.isDaemon());
       System.out.println("демон?.. " + thread2.isDaemon());
       System.out.println("демон?.. " + thread3.isDaemon());

       thread1.start();
       thread2.start();
       thread3.start();
   }
}
Keluaran konsol:

демон?.. true
демон?.. false
демон?.. false
daemon thread
user thread
user thread
Dari output kita melihat bahwa di dalam thread itu sendiri, dengan menggunakan currentThread()metode statis, kita bisa mengetahui thread mana yang ada di satu sisi, di sisi lain, jika kita memiliki referensi ke objek thread ini, kita bisa mengetahuinya langsung darinya. Hal ini memberikan fleksibilitas yang diperlukan dalam konfigurasi.

44. Apakah mungkin menjadikan thread sebagai daemon setelah dibuat?

TIDAK. Jika Anda melakukan ini, pengecualian akan muncul IllegalThreadStateException. Oleh karena itu, kita hanya dapat membuat thread daemon sebelum dimulai. Contoh:
class SetDaemonAfterStartExample extends Thread {

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

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

       // здесь будет выброшено исключение
       afterStartExample.setDaemon(true);
   }
}
Keluaran konsol:

Working...
Exception in thread "main" java.lang.IllegalThreadStateException
	at java.lang.Thread.setDaemon(Thread.java:1359)
	at SetDaemonAfterStartExample.main(SetDaemonAfterStartExample.java:14)

45. Apa yang dimaksud dengan kait penutup?

Shutdownhook adalah thread yang secara implisit dipanggil sebelum JVM (Java Virtual Machine) dimatikan. Jadi kita bisa menggunakannya untuk membersihkan sumber daya atau menyimpan status ketika Java Virtual Machine mati secara normal atau tiba-tiba. Kita dapat menambahkan shutdown hookmenggunakan metode berikut:
Runtime.getRuntime().addShutdownHook(new ShutdownHookThreadExample());
Seperti yang ditunjukkan pada contoh:
/**
* Программа, которая показывает How запустить shutdown hook тред,
* который выполнится аккурат до окончания работы JVM
*/
class ShutdownHookThreadExample extends Thread {

   public void run() {
       System.out.println("shutdown hook задачу выполнил");
   }

   public static void main(String[] args) {

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

       System.out.println("Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.");
       try {
           Thread.sleep(60000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}
Keluaran konsol:

Теперь программа засыпает, нажмите ctrl+c чтоб завершить ее.
shutdown hook задачу выполнил

46. ​​​​Apa itu sinkronisasi?

Sinkronisasi di Java adalah kemampuan untuk mengontrol akses beberapa thread ke sumber daya bersama. Ketika beberapa thread mencoba melakukan tugas yang sama, ada kemungkinan hasil yang salah, sehingga untuk mengatasi masalah ini, Java menggunakan sinkronisasi, sehingga hanya satu thread yang dapat bekerja dalam satu waktu. Sinkronisasi dapat dicapai dengan tiga cara:
  • Metode Sinkronisasi
  • Dengan menyinkronkan blok tertentu
  • Sinkronisasi statis

Sinkronisasi metode

Metode tersinkronisasi digunakan untuk mengunci objek untuk sumber daya bersama apa pun. Ketika sebuah thread memanggil metode tersinkronisasi, secara otomatis ia memperoleh kunci pada objek tersebut dan melepaskannya ketika thread tersebut menyelesaikan tugasnya. Untuk membuatnya berfungsi, Anda perlu menambahkan kata kunci tersinkronisasi . Mari kita lihat cara kerjanya dengan sebuah contoh:
/**
* Пример, где мы синхронизируем метод. То есть добавляем ему слово synchronized.
* Есть два писателя, которые хотят использовать один принтер. Они подготовor свои поэмы
* И конечно же не хотят, чтоб их поэмы перемешались, а хотят, чтоб работа была сделана по * * * очереди для каждого из них
*/
class Printer {

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

   public static void main(String args[]) {
       // один an object для двух тредов
       Printer printer  = new Printer();

       // создаем два треда
       Writer1 writer1 = new Writer1(printer);
       Writer2 writer2 = new Writer2(printer);

       // запускаем их
       writer1.start();
       writer2.start();
   }
}

/**
* Писатель номер 1, который пишет свою поэму.
*/
class Writer1 extends Thread {
   Printer printer;

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

   public void run() {
       List<string> poem = Arrays.asList("Я ", this.getName(), " Пишу", " Письмо");
       printer.print(poem);
   }

}

/**
* Писатель номер 2, который пишет свою поэму.
*/
class Writer2 extends Thread {
   Printer printer;

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

   public void run() {
       List<String> poem = Arrays.asList("Не Я ", this.getName(), " Не пишу", " Не Письмо");
       printer.print(poem);
   }
}
Dan output ke konsol:

Я Thread-0 Пишу Письмо
Не Я Thread-1 Не пишу Не Письмо

Blok sinkronisasi

Blok tersinkronisasi dapat digunakan untuk melakukan sinkronisasi pada sumber daya metode tertentu. Katakanlah dalam metode besar (ya, ya, Anda tidak dapat menulis hal seperti itu, tetapi terkadang hal itu terjadi) Anda hanya perlu menyinkronkan sebagian kecil, karena alasan tertentu. Jika Anda memasukkan semua kode suatu metode ke dalam blok tersinkronisasi, maka cara kerjanya akan sama seperti metode tersinkronisasi. Sintaksnya terlihat seperti ini:
synchronized (“an object для блокировки”) {
   // сам code, который нужно защитить
}
Agar tidak mengulangi contoh sebelumnya, kami akan membuat thread melalui kelas anonim - yaitu, segera mengimplementasikan antarmuka Runnable.
/**
* Вот How добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {

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

   public static void main(String args[]) {
       // один an object для двух тредов
       Printer printer = new Printer();

       // создаем два треда
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
               printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
               printer.print(poem);
           }
       });

       // запускаем их
       writer1.start();
       writer2.start();
   }
}

}
dan output ke konsol

Я Writer1 Пишу Письмо
Не Я Writer2 Не пишу Не Письмо

Sinkronisasi statis

Jika Anda membuat metode statis disinkronkan, kuncinya akan berada di kelas, bukan pada objek. Dalam contoh ini, kami menerapkan kata kunci sinkronisasi ke metode statis untuk melakukan sinkronisasi statis:
/**
* Вот How добавляется блок синхронизации.
* Внутри нужно указать у кого будет взят мьютекс для блокировки.
*/
class Printer {

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

   public static void main(String args[]) {

       // создаем два треда
       Thread writer1 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Я ", "Writer1", " Пишу", " Письмо");
               Printer.print(poem);
           }
       });
       Thread writer2 = new Thread(new Runnable() {
           @Override
           public void run() {
               List<String> poem = Arrays.asList("Не Я ", "Writer2", " Не пишу", " Не Письмо");
               Printer.print(poem);
           }
       });

       // запускаем их
       writer1.start();
       writer2.start();
   }
}
dan output ke konsol:

Не Я Writer2 Не пишу Не Письмо
Я Writer1 Пишу Письмо

47. Apa yang dimaksud dengan variabel volatil?

Kata kunci volatiledigunakan dalam pemrograman multi-thread untuk memberikan keamanan thread karena modifikasi pada satu variabel yang dapat diubah dapat dilihat oleh semua thread lainnya, sehingga satu variabel dapat digunakan oleh satu thread pada satu waktu. Dengan menggunakan kata kunci tersebut, volatileAnda dapat menjamin bahwa variabel tersebut akan aman untuk thread dan akan disimpan di memori bersama, dan thread tidak akan memasukkannya ke dalam cache. Seperti apa bentuknya?
private volatile AtomicInteger count;
Kita tinggal menambahkan variabelnya volatile. Tapi ini tidak berarti keamanan thread lengkap... Lagi pula, operasi mungkin tidak bersifat atomik pada suatu variabel. Tapi Anda bisa menggunakan Atomickelas yang melakukan operasi secara atom, yaitu dalam satu eksekusi oleh prosesor. Banyak kelas seperti itu dapat ditemukan dalam paket java.util.concurrent.atomic.

48. Apa itu kebuntuan

Kebuntuan di Java adalah bagian dari multithreading. Kebuntuan dapat terjadi dalam situasi di mana sebuah thread menunggu pada kunci objek yang diperoleh oleh thread lain, dan thread kedua menunggu pada kunci objek yang diperoleh oleh thread pertama. Jadi, kedua thread ini menunggu satu sama lain dan tidak akan melanjutkan mengeksekusi kodenya. 50 Pertanyaan dan Jawaban Wawancara Inti Java Teratas.  Bagian 3 - 5Mari kita lihat Contoh di mana terdapat kelas yang mengimplementasikan Runnable. Ia menerima dua sumber daya di konstruktornya. Di dalam metode run(), dibutuhkan kuncinya satu per satu, jadi jika Anda membuat dua objek kelas ini dan mentransfer sumber daya dalam urutan berbeda, Anda dapat dengan mudah mengalami kunci:
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();
   }
}

/**
* Класс, который принимает два ресурса.
*/
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() + " захватил ресурс: " + r1);

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

           synchronized (r2) {
               System.out.println(Thread.currentThread().getName() + " захватил ресурс: " + r2);
           }
       }
   }
}
Keluaran konsol:

Первый тред захватил первый ресурс
Второй тред захватывает второй ресурс

49. Bagaimana cara menghindari kebuntuan?

Berdasarkan apa yang kita ketahui bagaimana kebuntuan terjadi, kita dapat menarik beberapa kesimpulan...
  • Seperti yang ditunjukkan pada contoh di atas, kebuntuan terjadi karena adanya kunci yang bertumpuk. Artinya, di dalam satu gembok terdapat gembok lain atau lebih. Anda dapat menghindari hal ini dengan cara berikut - alih-alih membuat sarang, Anda perlu menambahkan abstraksi baru di atas dan memberikan kunci ke tingkat yang lebih tinggi, dan menghapus kunci yang bersarang.
  • Semakin banyak pemblokiran, semakin besar peluang terjadinya kebuntuan. Oleh karena itu, setiap kali Anda menambahkan kunci, Anda perlu memikirkan apakah itu benar-benar diperlukan dan apakah penambahan yang baru dapat dihindari.
  • Kegunaan Thread.join(). Deadlock juga bisa terjadi ketika satu thread sedang menunggu thread lainnya. Untuk menghindari masalah ini, Anda mungkin mempertimbangkan untuk menetapkan batas waktu pada join()metode ini.
  • Kalau kita punya satu thread, tidak akan ada deadlock ;)

50. Apa yang dimaksud dengan kondisi balapan?

Jika dalam balapan nyata mobil tampil, maka dalam terminologi balap multi-threading, thread tampil di balapan. Tapi kenapa? Ada dua thread yang sedang berjalan dan dapat memiliki akses ke objek yang sama. Dan mereka dapat mencoba memperbarui status pada saat yang bersamaan. Sejauh ini semuanya jelas, bukan? Jadi thread bekerja baik secara paralel nyata (jika ada lebih dari satu inti dalam prosesor) atau secara paralel bersyarat, ketika prosesor mengalokasikan waktu yang singkat. Dan kami tidak dapat mengontrol proses ini, jadi kami tidak dapat menjamin bahwa ketika satu thread membaca data dari suatu objek, ia akan mempunyai waktu untuk mengubahnya SEBELUM thread lain melakukannya. Masalah seperti ini terjadi ketika kombinasi uji-dan-tindakan ini berhasil. Apa artinya? Misalnya, kita mempunyai ifekspresi yang kondisinya sendiri berubah, yaitu:
int z = 0;

// проверь
if (z < 5) {
//действуй
   z = z + 5;
}
Jadi mungkin ada situasi ketika dua thread secara bersamaan memasukkan blok kode ini pada saat z masih sama dengan nol dan bersama-sama mereka mengubah nilai ini. Dan pada akhirnya kita tidak akan mendapatkan nilai yang diharapkan yaitu 5, melainkan 10. Bagaimana cara menghindarinya? Anda perlu mengunci sebelum dan sesudah eksekusi. Artinya, agar thread pertama memasuki blok if, lakukan semua tindakan, ubah, zdan baru kemudian berikan kesempatan kepada thread berikutnya untuk melakukan ini. Tetapi utas berikutnya tidak akan masuk ke blok if, karena zsudah sama dengan 5:
// получить блокировку для z
if (z < 5) {
   z = z + 5;
}
// выпустить из блокировки z
===================================================

Alih-alih keluaran

Saya ingin mengucapkan terima kasih kepada semua orang yang membaca sampai akhir. Itu adalah perjalanan yang panjang dan Anda berhasil! Tidak semuanya mungkin jelas. Ini baik-baik saja. Segera setelah saya mulai belajar Java, saya tidak mengerti apa itu variabel statis. Tapi tidak ada apa-apa, saya tertidur dengan pemikiran ini, membaca beberapa sumber lagi dan akhirnya mengerti. Mempersiapkan wawancara lebih merupakan masalah akademis daripada masalah praktis. Oleh karena itu, sebelum setiap wawancara, Anda perlu mengulang dan menyegarkan ingatan Anda tentang hal-hal yang mungkin jarang Anda gunakan.

Dan seperti biasa, tautan bermanfaat:

Terima kasih sudah membaca, Sampai jumpa lagi) Profil saya di GitHub
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION