JavaRush /Blog Java /Random-MS /Analisis soalan dan jawapan daripada temu bual untuk pemb...

Analisis soalan dan jawapan daripada temu bual untuk pembangun Java. Bahagian 12

Diterbitkan dalam kumpulan
hello! Pengetahuan adalah kuasa. Lebih banyak pengetahuan anda sebelum temu duga pertama anda, lebih yakin anda akan merasainya. Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 1Dengan jumlah pengetahuan yang baik, anda akan sukar untuk mengelirukan, dan pada masa yang sama anda akan dapat mengejutkan penemuduga anda. Oleh itu, hari ini, tanpa berlengah lagi, kami akan terus mengukuhkan asas teori anda dengan meneliti 250+ soalan untuk pembangun Java . Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 2

103. Apakah peraturan untuk menyemak pengecualian dalam warisan?

Jika saya memahami soalan dengan betul, mereka bertanya tentang peraturan untuk bekerja dengan pengecualian semasa pewarisan, dan ia adalah seperti berikut:
  • Kaedah yang ditindih atau dilaksanakan dalam keturunan/pelaksanaan tidak boleh membuang pengecualian yang diperiksa yang lebih tinggi dalam hierarki daripada pengecualian dalam kaedah superclass/antara muka.
Iaitu, jika kita mempunyai antara muka Haiwan tertentu dengan kaedah yang membuang IOException :
public  interface Animal {
   void voice() throws IOException;
}
Dalam pelaksanaan antara muka ini, kita tidak boleh membuang pengecualian lontaran yang lebih umum (contohnya, Exception , Throwable ), tetapi kita boleh menggantikannya dengan pengecualian keturunan, seperti FileNotFoundException :
public class Cat implements Animal {
   @Override
   public void voice() throws FileNotFoundException {
// некоторая реализация
   }
}
  • Pembina subkelas mesti memasukkan dalam lemparannya menyekat semua kelas pengecualian yang dilemparkan oleh pembina kelas super yang dipanggil apabila objek dicipta.
Katakan pembina kelas Haiwan melemparkan banyak pengecualian:
public class Animal {
  public Animal() throws ArithmeticException, NullPointerException, IOException {
  }
Kemudian pewaris kelas juga mesti menunjukkan mereka dalam pembina:
public class Cat extends Animal {
   public Cat() throws ArithmeticException, NullPointerException, IOException {
       super();
   }
Atau, seperti dalam kes kaedah, anda boleh menentukan bukan pengecualian yang sama, tetapi yang lebih umum. Dalam kes kami, sudah cukup untuk menentukan pengecualian yang lebih umum - Exception , kerana ini adalah nenek moyang yang sama bagi ketiga-tiga pengecualian yang dipertimbangkan:
public class Cat extends Animal {
   public Cat() throws Exception {
       super();
   }

104. Bolehkah anda menulis kod apabila blok akhirnya tidak akan dilaksanakan?

Pertama, mari kita ingat apa yang akhirnya . Sebelum ini, kami melihat mekanisme untuk menangkap pengecualian: blok cuba menggariskan kawasan penangkapan, manakala blok tangkapan ialah kod yang akan berfungsi apabila pengecualian tertentu dilemparkan. Akhirnya ialah blok ketiga kod selepas akhirnya yang boleh ditukar ganti dengan tangkapan tetapi tidak saling eksklusif. Intipati blok ini ialah kod di dalamnya sentiasa berfungsi, tanpa mengira hasil percubaan atau tangkapan ( tidak kira sama ada pengecualian telah dilemparkan atau tidak). Kes kegagalannya sangat jarang berlaku dan ianya tidak normal. Kes kegagalan yang paling mudah ialah apabila kaedah System.exit(0) dipanggil dalam kod di atas , yang menamatkan program (memadamkannya):
try {
   throw new IOException();
} catch (IOException e) {
   System.exit(0);
} finally {
   System.out.println("Данное сообщение не будет выведенно в консоль");
}
Terdapat juga beberapa situasi lain yang akhirnya tidak akan berfungsi:
  • Penamatan program yang tidak normal yang disebabkan oleh masalah sistem kritikal, atau kejatuhan beberapa Ralat yang akan "menghancurkan" aplikasi (contoh ralat boleh menjadi StackOwerflowError yang sama yang berlaku apabila memori tindanan melimpah).
  • Apabila benang deamon melalui ry...akhirnya sekat dan selari dengan ini program tamat. Lagipun, benang deamon adalah benang untuk tindakan latar belakang, iaitu, ia bukan keutamaan dan wajib, dan aplikasi tidak akan menunggu kerjanya selesai.
  • Gelung tak terhingga yang paling biasa, dalam try or catch , sekali di mana aliran akan kekal di sana selama-lamanya:

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

Soalan ini agak popular dalam temu bual untuk pemula, jadi beberapa situasi luar biasa ini patut diingati. Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 3

105. Tulis satu contoh pengendalian berbilang pengecualian dalam satu blok tangkapan

1) Mungkin soalan itu ditanya dengan salah. Setakat yang saya faham, soalan ini merujuk kepada beberapa tangkapan untuk satu blok percubaan :
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 pengecualian berlaku dalam blok cuba , maka blok tangkapan cuba menangkapnya secara bergilir-gilir dari atas ke bawah. Jika blok tangkapan tertentu berjaya, ia mendapat hak untuk mengendalikan pengecualian itu, manakala blok selebihnya di bawah tidak lagi boleh cuba menangkapnya dan memprosesnya dengan cara mereka sendiri. Oleh itu, pengecualian yang lebih sempit diletakkan lebih tinggi dalam rantai blok tangkapan , dan pengecualian yang lebih luas diletakkan lebih rendah. Sebagai contoh, jika dalam blok tangkapan pertama kami pengecualian kelas Pengecualian ditangkap , maka pengecualian yang diperiksa tidak akan dapat masuk ke dalam blok yang tinggal (selebihnya blok dengan keturunan Pengecualian akan menjadi tidak berguna sama sekali). 2) Soalan telah ditanya dengan betul. Dalam kes ini, pemprosesan kami akan kelihatan 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 cuba mengetahui jenis khususnya melalui kaedah instanceof , yang digunakan untuk menyemak sama ada objek tergolong dalam jenis tertentu, supaya kemudiannya kami boleh mengecilkannya kepada jenis ini tanpa akibat negatif. Kedua-dua pendekatan yang dipertimbangkan boleh digunakan dalam situasi yang sama, tetapi saya mengatakan bahawa soalan itu tidak betul kerana saya tidak akan memanggil pilihan kedua yang baik dan tidak pernah melihatnya dalam amalan saya, sementara pada masa yang sama kaedah pertama dengan multicatches telah diterima secara meluas. perhatian.menyebarkan. Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 4

106. Pengendali manakah yang membenarkan anda memaksa pengecualian dilemparkan? Tulis satu contoh

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

107. Bolehkah kaedah utama melontar pengecualian lontaran? Jika ya, ke mana ia akan dipindahkan?

Pertama sekali, saya ingin ambil perhatian bahawa utama tidak lebih daripada kaedah biasa, dan ya, ia dipanggil oleh mesin maya untuk mula melaksanakan program, tetapi selain itu, ia boleh dipanggil dari mana-mana kod lain. Iaitu, ia juga tertakluk kepada peraturan biasa untuk menentukan pengecualian yang diperiksa selepas lontaran :
public static void main(String[] args) throws IOException {
Sehubungan itu, pengecualian juga mungkin berlaku di dalamnya. Jika main tidak dipanggil dalam beberapa kaedah, tetapi telah dimulakan sebagai titik pelancaran program, maka pengecualian yang dilemparkan olehnya akan dikendalikan oleh pemintas .UncaughtExceptionHandler . Pengendali ini adalah satu setiap utas (iaitu, satu pengendali dalam setiap utas). Jika perlu, anda boleh mencipta pengendali anda sendiri dan menetapkannya menggunakan kaedah setDefaultUncaughtExceptionHandler yang dipanggil pada objek Thread .

Multithreading

Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 5

108. Apakah alatan yang anda tahu untuk bekerja dengan multithreading?

Alat Asas/Asas untuk Menggunakan Multithreading dalam Java:
  • Disegerakkan ialah mekanisme untuk menutup (menyekat) kaedah/blok apabila benang memasukinya, daripada benang lain.
  • Meruap ialah mekanisme untuk memastikan capaian yang konsisten kepada pembolehubah oleh benang yang berbeza, iaitu, dengan kehadiran pengubah suai ini pada pembolehubah, semua operasi tugasan dan bacaan mestilah atom. Dalam erti kata lain, benang tidak akan menyalin pembolehubah ini ke memori tempatan mereka dan mengubahnya, tetapi akan menukar nilai asalnya.
Baca lebih lanjut mengenai tidak menentu di sini .
  • Runnable ialah antara muka yang boleh dilaksanakan (khususnya, kaedah lariannya) dalam kelas tertentu:
public class CustomRunnable implements Runnable {
   @Override
   public void run() {
       // некоторая логика
   }
}
Dan setelah mencipta objek kelas ini, anda boleh memulakan utas baharu dengan menetapkan objek ini dalam pembina objek Thread baharu dan memanggil kaedah start() :
Runnable runnable = new CustomRunnable();
new Thread(runnable).start();
Kaedah mula menjalankan kaedah run() yang dilaksanakan dalam benang berasingan.
  • Thread ialah kelas, mewarisi dari mana (semasa mengatasi kaedah run ):
public class CustomThread extends Thread {
   @Override
   public void run() {
       // некоторая логика
   }
}
Dan dengan mencipta objek kelas ini dan melancarkannya menggunakan kaedah start() , dengan itu kami akan melancarkan utas baharu:
new CustomThread().start();
  • Concurrency ialah pakej dengan alatan untuk bekerja dalam persekitaran berbilang benang.
Ia terdiri daripada:
  • Koleksi Serentak - satu set koleksi khusus untuk bekerja dalam persekitaran berbilang benang.
  • Baris gilir - baris gilir khusus untuk persekitaran berbilang benang (menyekat dan tidak menyekat).
  • Penyegerak ialah utiliti khusus untuk bekerja dalam persekitaran berbilang benang.
  • Pelaksana ialah mekanisme untuk mencipta kumpulan benang.
  • Kunci - mekanisme penyegerakan benang (lebih fleksibel daripada yang standard - disegerakkan, tunggu, maklumkan, maklumkanSemua).
  • Atomics ialah kelas yang dioptimumkan untuk pelaksanaan berbilang benang; setiap operasi adalah atom.
Baca lebih lanjut mengenai pakej serentak di sini .

109. Bercakap tentang penyegerakan antara benang. Apakah kaedah wait(), notify() - notifyAll() join() digunakan?

Setakat yang saya faham soalan itu, penyegerakan antara utas adalah mengenai pengubah suai utama - synchronized . Pengubah suai ini boleh diletakkan sama ada di sebelah blok:
synchronized (Main.class) {
   // некоторая логика
}
Atau terus dalam tandatangan kaedah:
public synchronized void move() {
   // некоторая логика}
Seperti yang saya katakan sebelum ini, disegerakkan ialah mekanisme yang membolehkan anda menutup blok/kaedah daripada utas lain apabila satu utas telah memasukinya. Fikirkan blok/kaedah sebagai bilik. Beberapa aliran, setelah datang ke sana, akan memasukinya dan menguncinya, aliran lain, setelah datang ke bilik dan melihat bahawa ia ditutup, akan menunggu di dekatnya sehingga ia bebas. Setelah menjalankan perniagaannya, benang pertama meninggalkan bilik dan melepaskan kunci. Dan bukan untuk apa-apa saya sentiasa bercakap tentang kunci, kerana ia benar-benar wujud. Ini adalah objek khas yang mempunyai keadaan sibuk/bebas. Objek ini dilampirkan pada setiap objek Java, jadi apabila menggunakan blok yang disegerakkan kita perlu menunjukkan dalam kurungan objek yang mutexnya kita mahu tutup pintunya:
Cat cat = new Cat();
synchronized (cat) {
   // некоторая логика
}
Anda juga boleh menggunakan mutex kelas, seperti yang saya lakukan dalam contoh pertama ( Main.class ). Apabila kita menggunakan kaedah yang disegerakkan , kita tidak menentukan objek yang ingin kita tutup, bukan? Dalam kes ini, untuk kaedah bukan statik, ia akan ditutup pada mutex objek ini , iaitu, objek semasa kelas ini. Yang statik akan ditutup pada mutex kelas semasa ( this.getClass(); ). Anda boleh membaca lebih lanjut mengenai mutex di sini . Nah, baca tentang disegerakkan di sini . Wait() ialah kaedah yang melepaskan mutex dan meletakkan benang semasa ke dalam mod siap sedia, seolah-olah dilampirkan pada monitor semasa (sesuatu seperti sauh). Disebabkan ini, kaedah ini hanya boleh dipanggil dari blok atau kaedah yang disegerakkan (jika tidak, apakah yang harus dibebaskan dan apa yang diharapkan). Juga ambil perhatian bahawa ini adalah kaedah kelas Objek . Lebih tepat lagi, bukan satu, malah tiga:
  • Wait() - meletakkan benang semasa ke dalam mod tunggu sehingga thread lain memanggil kaedah notify() atau notifyAll() untuk objek ini (kita akan bercakap tentang kaedah ini kemudian).

  • Tunggu (masa tamat lama) - meletakkan utas semasa ke dalam mod tunggu sehingga utas lain memanggil kaedah notify() atau notifyAll() pada objek ini atau tamat masa yang ditentukan tamat tempoh .

  • Tunggu (masa tamat lama, int nanos) - serupa dengan yang sebelumnya, hanya nano yang membolehkan anda menentukan nanosaat (tetapan masa yang lebih tepat).

  • Notify() ialah kaedah yang membolehkan anda membangunkan satu utas rawak blok penyegerakan semasa. Sekali lagi, ia hanya boleh dipanggil dalam blok atau kaedah yang disegerakkan (lagipun, di tempat lain ia tidak akan mempunyai sesiapa untuk dinyahbeku).

  • NotifyAll() ialah kaedah yang membangunkan semua utas menunggu pada monitor semasa (juga digunakan hanya dalam blok atau kaedah yang disegerakkan ).

110. Bagaimana untuk menghentikan aliran?

Perkara pertama yang perlu dikatakan ialah apabila kaedah run() dilaksanakan sepenuhnya , benang dimusnahkan secara automatik. Tetapi kadangkala anda perlu membunuhnya lebih awal daripada jadual, sebelum kaedah ini selesai. Jadi apa yang perlu kita lakukan? Mungkin objek Thread harus mempunyai kaedah stop() ? Tidak kira bagaimana keadaannya! Kaedah ini dianggap ketinggalan zaman dan boleh menyebabkan ranap sistem. Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 6Nah, kemudian apa? Terdapat dua cara untuk melakukan ini: Yang pertama ialah menggunakan bendera boolean dalaman anda. Mari kita lihat contoh. Kami mempunyai pelaksanaan kami sendiri bagi urutan yang harus memaparkan frasa tertentu pada skrin sehingga ia 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;
   }
}
Apabila menggunakan kaedah stopRunning() , bendera dalaman menjadi palsu dan kaedah larian berhenti berjalan. Mari jalankannya dalam utama :
System.out.println("Начало выполнения программы");
CustomThread thread = new CustomThread();
thread.start();
Thread.sleep(3);
// пока наш основной поток спит, вспомогательный  CustomThread работает и выводит в коноль своё сообщение
thread.stopRunningThread();
System.out.println("Конец выполнения программы");
Akibatnya, kita akan melihat sesuatu seperti ini dalam konsol:
Permulaan pelaksanaan program Benang sedang melaksanakan beberapa logik... Benang sedang melaksanakan beberapa logik... Benang sedang melaksanakan beberapa logik... Benang sedang melaksanakan beberapa logik... Benang sedang melaksanakan beberapa logik... The utas sedang melaksanakan beberapa logik... Tamat pelaksanaan program Benang dihentikan !
Ini bermakna urutan kami berfungsi, mengeluarkan beberapa mesej ke konsol dan berjaya dihentikan. Saya perhatikan bahawa bilangan output mesej akan berbeza-beza dari run ke run; kadangkala benang tambahan tidak mengeluarkan apa-apa pun. Seperti yang saya perhatikan, ini bergantung pada masa tidur benang utama, semakin lama, semakin kecil kemungkinan benang tambahan tidak akan mengeluarkan apa-apa. Dengan masa tidur 1ms, mesej hampir tidak pernah dikeluarkan, tetapi jika anda menetapkannya kepada 20ms, ia hampir selalu berfungsi. Mungkin, apabila masanya singkat, benang itu tidak mempunyai masa untuk memulakan dan memulakan kerjanya, dan segera dihentikan. Cara kedua ialah menggunakan kaedah interrupted() pada objek Thread , yang mengembalikan nilai bendera interrupted dalaman (bendera ini palsu secara lalai ) dan kaedah interrupt() yang lain , yang menetapkan bendera ini kepada true (apabila ini bendera adalah benar benang harus menghentikan kerjanya) . Mari lihat 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 pelaksanaan akan sama seperti dalam kes pertama, tetapi saya lebih suka pendekatan ini: kami menulis lebih sedikit kod dan menggunakan lebih banyak fungsi standard yang sudah siap. Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 7Di situlah kita akan berhenti hari ini.Analisis soalan dan jawapan daripada temu bual untuk pembangun Java.  Bahagian 12 - 8
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION