JavaRush /Java Blog /Random-ID /Analisis tanya jawab dari wawancara untuk pengembang Java...

Analisis tanya jawab dari wawancara untuk pengembang Java. Bagian 12

Dipublikasikan di grup Random-ID
Halo! Pengetahuan adalah kekuatan. Semakin banyak pengetahuan yang Anda miliki sebelum wawancara pertama, Anda akan semakin percaya diri. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 1Dengan pengetahuan yang cukup, Anda akan sulit untuk dibingungkan, dan pada saat yang sama Anda akan dapat memberikan kejutan yang menyenangkan kepada pewawancara Anda. Oleh karena itu, hari ini, tanpa basa-basi lagi, kami akan terus memperkuat landasan teori Anda dengan memeriksa 250+ pertanyaan untuk pengembang Java . Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 2

103. Bagaimana aturan pemeriksaan pengecualian dalam pewarisan?

Jika saya memahami pertanyaannya dengan benar, mereka menanyakan tentang aturan bekerja dengan pengecualian selama pewarisan, dan itu adalah sebagai berikut:
  • Metode yang ditimpa atau diimplementasikan dalam turunan/implementasi tidak dapat menampilkan pengecualian yang diperiksa yang hierarkinya lebih tinggi daripada pengecualian dalam metode superkelas/antarmuka.
Artinya, jika kita memiliki antarmuka Animal tertentu dengan metode yang menampilkan IOException :
public  interface Animal {
   void voice() throws IOException;
}
Dalam implementasi antarmuka ini, kita tidak bisa melemparkan pengecualian yang lebih umum (misalnya, Exception , Throwable ), namun kita bisa menggantinya dengan pengecualian turunan, seperti FileNotFoundException :
public class Cat implements Animal {
   @Override
   public void voice() throws FileNotFoundException {
// некоторая реализация
   }
}
  • Konstruktor subkelas harus menyertakan dalam blok lemparannya semua kelas pengecualian yang dilempar oleh konstruktor superkelas yang dipanggil saat membuat objek.
Misalkan konstruktor kelas Animal memberikan banyak pengecualian:
public class Animal {
  public Animal() throws ArithmeticException, NullPointerException, IOException {
  }
Kemudian pewaris kelas juga harus menunjukkannya di konstruktor:
public class Cat extends Animal {
   public Cat() throws ArithmeticException, NullPointerException, IOException {
       super();
   }
Atau, seperti halnya metode, Anda tidak dapat menentukan pengecualian yang sama, tetapi pengecualian yang lebih umum. Dalam kasus kami, cukup dengan menentukan pengecualian yang lebih umum - Exception , karena ini adalah nenek moyang yang sama dari ketiga pengecualian yang dipertimbangkan:
public class Cat extends Animal {
   public Cat() throws Exception {
       super();
   }

104. Bisakah Anda menulis kode ketika blok akhirnya tidak dieksekusi?

Pertama, mari kita ingat apa yang akhirnya . Sebelumnya, kita melihat mekanisme untuk menangkap pengecualian: blok try menguraikan area penangkapan, sedangkan blok catch adalah kode yang akan berfungsi ketika pengecualian tertentu dilemparkan. Akhirnya adalah blok kode ketiga setelahnya yang dapat dipertukarkan dengan catch tetapi tidak eksklusif satu sama lain. Inti dari blok ini adalah bahwa kode di dalamnya selalu berfungsi, terlepas dari hasil try atau catch (terlepas dari apakah pengecualian dilempar atau tidak). Kasus kegagalannya sangat jarang terjadi dan tidak normal. Kasus kegagalan yang paling sederhana adalah ketika metode System.exit(0) dipanggil dalam kode di atas , yang menghentikan program (memadamkannya):
try {
   throw new IOException();
} catch (IOException e) {
   System.exit(0);
} finally {
   System.out.println("Данное сообщение не будет выведенно в консоль");
}
Ada juga beberapa situasi lain yang akhirnya tidak akan berhasil:
  • Penghentian program yang tidak normal disebabkan oleh masalah sistem yang kritis, atau jatuhnya beberapa Kesalahan yang akan “menghancurkan” aplikasi (contoh kesalahan dapat berupa StackOwerflowError yang sama yang terjadi ketika memori tumpukan meluap).
  • Ketika thread deamon melewati blok ry...finally dan bersamaan dengan ini program berakhir. Bagaimanapun, thread deamon adalah thread untuk tindakan latar belakang, artinya, ini bukan prioritas dan wajib, dan aplikasi tidak akan menunggu sampai pekerjaannya selesai.
  • Perulangan tak terbatas yang paling umum, dalam try atau catch , sekali yang alirannya akan tetap ada di sana selamanya:

    try {
       while (true) {
       }
    } finally {
       System.out.println("Данное сообщение не будет выведенно в консоль");
    }

Pertanyaan ini cukup populer dalam wawancara untuk pemula, jadi beberapa situasi luar biasa ini patut diingat. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 3

105. Tuliskan contoh penanganan beberapa pengecualian dalam satu blok tangkapan

1) Mungkin pertanyaan yang diajukan salah. Sejauh yang saya mengerti, pertanyaan ini merujuk pada beberapa tangkapan untuk satu blok percobaan :
try {
  throw new FileNotFoundException();
} catch (FileNotFoundException e) {
   System.out.print("Упс, у вас упало исключение - " + e);
} catch (IOException e) {
   System.out.print("Упс, у вас упало исключение - " + e);
} catch (Exception e) {
   System.out.print("Упс, у вас упало исключение - " + e);
}
Jika terjadi eksepsi pada blok try , maka blok catch secara bergantian mencoba menangkapnya dari atas ke bawah. Jika blok catch tertentu berhasil, ia berhak menangani eksepsi tersebut, sedangkan blok-blok lain di bawahnya tidak lagi dapat ditangani. mampu mencoba menangkapnya dan mengolahnya dengan caranya sendiri. Oleh karena itu, pengecualian yang lebih sempit ditempatkan lebih tinggi dalam rantai blok tangkapan , dan pengecualian yang lebih luas ditempatkan lebih rendah. Misalnya, jika di blok catch pertama kita ada pengecualian dari kelas Exception yang tertangkap , maka pengecualian yang dicentang tidak akan bisa masuk ke blok yang tersisa (blok yang tersisa dengan keturunan Exception tidak akan berguna sama sekali). 2) Pertanyaan telah ditanyakan dengan benar, dalam hal ini proses kita akan terlihat seperti berikut:
try {
  throw new NullPointerException();
} catch (Exception e) {
   if (e instanceof FileNotFoundException) {
       // некоторая обработка с сужением типа (FileNotFoundException)e
   } else if (e instanceof ArithmeticException) {
       // некоторая обработка с сужением типа (ArithmeticException)e
   } else if(e instanceof NullPointerException) {
       // некоторая обработка с сужением типа (NullPointerException)e
   }
Setelah menangkap pengecualian melalui catch , kami mencoba mencari tahu tipe spesifiknya melalui metode instanceof , yang digunakan untuk memeriksa apakah suatu objek termasuk dalam tipe tertentu, sehingga nantinya kami dapat mempersempitnya ke tipe ini tanpa konsekuensi negatif. Kedua pendekatan yang dipertimbangkan dapat digunakan dalam situasi yang sama, tetapi saya mengatakan bahwa pertanyaannya salah karena saya tidak akan menyebut opsi kedua baik dan belum pernah melihatnya dalam praktik saya, sementara metode pertama dengan multicatch telah tersebar luas. perhatian.menyebar. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 4

106. Operator mana yang mengizinkan Anda untuk memaksa pelemparan pengecualian? Tulis sebuah contoh

Saya sudah menggunakannya beberapa kali di atas, namun saya akan mengulangi kata kunci ini - melempar . Contoh penggunaan (memaksa pengecualian):
throw new NullPointerException();

107. Bisakah metode utama memunculkan pengecualian lemparan? Kalau iya, transfernya kemana?

Pertama-tama, saya ingin mencatat bahwa main tidak lebih dari metode biasa, dan ya, ini dipanggil oleh mesin virtual untuk mulai menjalankan program, tetapi selain itu, dapat dipanggil dari kode lain. Artinya, ini juga tunduk pada aturan biasa untuk menentukan pengecualian yang dicentang setelah throws :
public static void main(String[] args) throws IOException {
Oleh karena itu, pengecualian juga dapat terjadi di dalamnya. Jika main tidak dipanggil dalam beberapa metode, tetapi dimulai sebagai titik peluncuran program, maka pengecualian yang diberikan olehnya akan ditangani oleh interseptor .UncaughtExceptionHandler . Penangan ini adalah satu per thread (yaitu, satu penangan di setiap thread). Jika perlu, Anda dapat membuat handler Anda sendiri dan mengaturnya menggunakan metode setDefaultUncaughtExceptionHandler yang dipanggil pada objek Thread .

Multithread

Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 5

108. Alat apa yang Anda ketahui untuk bekerja dengan multithreading?

Alat Dasar/Dasar untuk Menggunakan Multithreading di Java:
  • Synchronized merupakan mekanisme penutupan (blocking) suatu metode/blok ketika ada thread yang masuk ke dalamnya, dari thread lain.
  • Volatile adalah mekanisme untuk memastikan akses yang konsisten ke suatu variabel melalui thread yang berbeda, yaitu dengan kehadiran pengubah ini pada suatu variabel, semua operasi penugasan dan pembacaan harus bersifat atomik. Dengan kata lain, thread tidak akan menyalin variabel ini ke memori lokalnya dan mengubahnya, tetapi akan mengubah nilai aslinya.
Baca lebih lanjut tentang volatil di sini .
  • Runnable adalah antarmuka yang dapat diimplementasikan (khususnya, metode run-nya) di kelas tertentu:
public class CustomRunnable implements Runnable {
   @Override
   public void run() {
       // некоторая логика
   }
}
Dan setelah membuat objek dari kelas ini, Anda dapat memulai thread baru dengan mengatur objek ini di konstruktor objek Thread baru dan memanggil metode start()- nya :
Runnable runnable = new CustomRunnable();
new Thread(runnable).start();
Metode start menjalankan metode run() yang diimplementasikan di thread terpisah.
  • Thread adalah kelas, yang mewarisi dari mana (sambil mengganti metode run ):
public class CustomThread extends Thread {
   @Override
   public void run() {
       // некоторая логика
   }
}
Dan dengan membuat objek kelas ini dan meluncurkannya menggunakan metode start() , kita akan meluncurkan thread baru:
new CustomThread().start();
  • Konkurensi adalah paket dengan alat untuk bekerja di lingkungan multi-thread.
Terdiri dari:
  • Koleksi Bersamaan - sekumpulan koleksi yang dikhususkan untuk bekerja di lingkungan multi-utas.
  • Antrian - antrian khusus untuk lingkungan multi-thread (pemblokiran dan non-pemblokiran).
  • Sinkronisasi adalah utilitas khusus untuk bekerja di lingkungan multi-thread.
  • Pelaksana adalah mekanisme untuk membuat kumpulan thread.
  • Kunci - mekanisme sinkronisasi utas (lebih fleksibel daripada yang standar - disinkronkan, tunggu, beri tahu, beri tahuSemua).
  • Atomics adalah kelas yang dioptimalkan untuk eksekusi multi-thread; setiap operasi bersifat atomik.
Baca lebih lanjut tentang paket bersamaan di sini .

109. Bicara tentang sinkronisasi antar thread. Untuk apa metode wait(), notify() - notifyAll() join() digunakan?

Sejauh yang saya mengerti pertanyaannya, sinkronisasi antar utas adalah tentang pengubah kunci - synced . Pengubah ini dapat ditempatkan langsung di sebelah blok:
synchronized (Main.class) {
   // некоторая логика
}
Atau langsung di tanda tangan metode:
public synchronized void move() {
   // некоторая логика}
Seperti yang saya katakan sebelumnya, sinkronisasi adalah mekanisme yang memungkinkan Anda menutup blok/metode dari thread lain ketika salah satu thread sudah memasukinya. Bayangkan blok/metode sebagai sebuah ruangan. Beberapa aliran, setelah sampai di sana, akan masuk dan menguncinya, aliran lain, setelah datang ke ruangan dan melihat bahwa ruangan itu tertutup, akan menunggu di dekatnya sampai bebas. Setelah menyelesaikan tugasnya, thread pertama meninggalkan ruangan dan melepaskan kuncinya. Dan bukan tanpa alasan saya terus-menerus membicarakan kuncinya, karena kunci itu benar-benar ada. Ini adalah objek khusus yang mempunyai keadaan sibuk/bebas. Objek ini melekat pada setiap objek Java, jadi ketika menggunakan blok tersinkronisasi kita perlu menunjukkan dalam tanda kurung objek yang mutex-nya ingin kita tutup pintunya:
Cat cat = new Cat();
synchronized (cat) {
   // некоторая логика
}
Anda juga dapat menggunakan kelas mutex, seperti yang saya lakukan pada contoh pertama ( Main.class ). Saat kita menggunakan sinkronisasi pada suatu metode, kita tidak menentukan objek yang ingin kita tutup, bukan? Dalam hal ini, untuk metode non-statis, metode ini akan menutup mutex dari objek ini , yaitu objek saat ini dari kelas ini. Yang statis akan ditutup pada mutex kelas saat ini ( this.getClass(); ). Anda dapat membaca lebih lanjut tentang mutex di sini . Nah, baca tentang sinkronisasi di sini . Wait() adalah metode yang melepaskan mutex dan menempatkan thread saat ini ke mode standby, seolah-olah terpasang ke monitor saat ini (seperti jangkar). Oleh karena itu, metode ini hanya dapat dipanggil dari blok atau metode yang disinkronkan (jika tidak, metode apa yang harus digratiskan dan apa yang diharapkan). Perhatikan juga bahwa ini adalah metode kelas Object . Lebih tepatnya, bukan hanya satu, tapi bahkan tiga:
  • Wait() - menempatkan thread saat ini ke mode tunggu hingga thread lain memanggil metode notify() atau notifyAll() untuk objek ini (kita akan membicarakan metode ini nanti).

  • Tunggu (waktu tunggu lama) - menempatkan thread saat ini ke mode tunggu hingga thread lain memanggil metode notify() atau notifyAll() pada objek ini atau batas waktu yang ditentukan berakhir .

  • Tunggu (waktu tunggu lama, int nanos) - mirip dengan yang sebelumnya, hanya nanos yang memungkinkan Anda menentukan nanodetik (pengaturan waktu yang lebih tepat).

  • Notify() adalah metode yang memungkinkan Anda membangunkan satu thread acak dari blok sinkronisasi saat ini. Sekali lagi, ini hanya dapat dipanggil dalam blok atau metode yang disinkronkan (lagipula, di tempat lain tidak ada orang yang dapat mencairkannya).

  • NotifyAll() adalah metode yang membangunkan semua thread yang menunggu di monitor saat ini (juga hanya digunakan dalam blok atau metode yang disinkronkan ).

110. Bagaimana cara menghentikan arus?

Hal pertama yang harus dikatakan adalah ketika metode run() dijalankan sepenuhnya , thread secara otomatis dimusnahkan. Namun terkadang Anda perlu membunuhnya lebih awal, sebelum metode ini selesai. Jadi apa yang harus kita lakukan? Mungkin objek Thread harus memiliki metode stop() ? Tidak peduli bagaimana keadaannya! Cara ini dianggap ketinggalan jaman dan dapat mengakibatkan sistem crash. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 6Lalu bagaimana? Ada dua cara untuk melakukan ini: Yang pertama adalah dengan menggunakan flag boolean internal Anda. Mari kita lihat sebuah contoh. Kami memiliki implementasi thread kami sendiri yang akan menampilkan frasa tertentu di layar hingga berhenti sepenuhnya:
public class CustomThread extends Thread {
private boolean isActive;

   public CustomThread() {
       this.isActive = true;
   }

   @Override
   public void run() {
       {
           while (isActive) {
               System.out.println("Поток выполняет некую логику...");
           }
           System.out.println("Поток остановлен!");
       }
   }

   public void stopRunningThread() {
       isActive = false;
   }
}
Saat menggunakan metode stopRunning() , tanda internal menjadi salah dan metode run berhenti berjalan. Mari kita jalankan di main :
System.out.println("Начало выполнения программы");
CustomThread thread = new CustomThread();
thread.start();
Thread.sleep(3);
// пока наш основной поток спит, вспомогательный  CustomThread работает и выводит в коноль своё сообщение
thread.stopRunningThread();
System.out.println("Конец выполнения программы");
Hasilnya, kita akan melihat sesuatu seperti ini di konsol:
Mulai eksekusi program Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... Thread menjalankan beberapa logika... thread menjalankan beberapa logika... Akhir eksekusi program Thread dihentikan!
Ini berarti thread kami berfungsi, mengeluarkan sejumlah pesan ke konsol dan berhasil dihentikan. Saya perhatikan bahwa jumlah keluaran pesan akan bervariasi dari satu proses ke proses lainnya; terkadang thread tambahan bahkan tidak menghasilkan apa pun. Seperti yang saya perhatikan, ini tergantung pada waktu tidur thread utama, semakin lama, semakin kecil kemungkinan thread tambahan tidak menghasilkan apa pun. Dengan waktu tidur 1 md, pesan hampir tidak pernah dikeluarkan, tetapi jika Anda menyetelnya ke 20 md, pesan hampir selalu berhasil. Mungkin, ketika waktunya singkat, thread tidak punya waktu untuk memulai dan memulai pekerjaannya, dan segera dihentikan. Cara kedua adalah dengan menggunakan metode interupsi() pada objek Thread , yang mengembalikan nilai flag interupsi internal (flag ini adalah false secara default ) dan metode interupsi() lainnya , yang menyetel flag ini ke true (saat ini benderanya benar , utasnya harus berhenti berfungsi). Mari kita lihat sebuah contoh:
public class CustomThread extends Thread {

   @Override
   public void run() {
       {
           while (!Thread.interrupted()) {
               System.out.println("Поток выполняет некую логику...");
           }
           System.out.println("Поток остановлен!");
       }
   }
}
Jalankan di utama :
System.out.println("Начало выполнения программы");
Thread thread = new CustomThread();
thread.start();
Thread.sleep(3);
thread.interrupt();
System.out.println("Конец выполнения программы");
Hasil eksekusi akan sama seperti pada kasus pertama, tetapi saya lebih menyukai pendekatan ini: kami menulis lebih sedikit kode dan menggunakan lebih banyak fungsionalitas standar yang sudah jadi. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 7Di situlah kita akan berhenti hari ini.Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 12 - 8
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION