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

Analisis tanya jawab dari wawancara untuk pengembang Java. Bagian 14

Dipublikasikan di grup Random-ID
Kembang api! Dunia terus bergerak dan kita pun terus bergerak. Sebelumnya, untuk menjadi pengembang Java, cukup mengetahui sedikit sintaksis Java, dan sisanya akan menyusul. Seiring berjalannya waktu, tingkat pengetahuan yang dibutuhkan untuk menjadi pengembang Java telah meningkat secara signifikan, begitu pula persaingan, yang terus meningkatkan standar pengetahuan yang dibutuhkan. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 1Jika Anda benar-benar ingin menjadi seorang pengembang, Anda harus menerima begitu saja dan mempersiapkan diri secara matang untuk menonjol di antara pemula seperti Anda. Yang akan kami lakukan hari ini adalah kami akan terus menganalisis 250+ pertanyaan . Pada artikel sebelumnya, kita telah membahas semua soal tingkat junior, dan hari ini kita akan menjawab soal tingkat menengah. Meskipun saya perhatikan bahwa ini bukan 100% pertanyaan tingkat menengah, Anda dapat menemui sebagian besar pertanyaan tersebut pada wawancara tingkat junior, karena pada wawancara seperti itulah penyelidikan terperinci atas dasar teori Anda dilakukan, sedangkan untuk siswa menengah pertanyaan lebih fokus untuk menyelidiki pengalamannya. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 2Tapi, tanpa basa-basi lagi, mari kita mulai.

Tengah

Biasa saja

1. Apa kelebihan dan kekurangan OOP jika dibandingkan dengan pemrograman prosedural/fungsional?

Ada pertanyaan ini dalam analisis pertanyaan untuk Junior, dan karenanya saya sudah menjawabnya. Carilah pertanyaan ini dan jawabannya di bagian artikel ini , pertanyaan 16 dan 17.

2. Apa perbedaan agregasi dengan komposisi?

Dalam OOP, terdapat beberapa jenis interaksi antar objek yang disatukan dalam konsep umum “Has-A Relationship”. Hubungan ini menunjukkan bahwa suatu objek merupakan komponen dari objek yang lain. Pada saat yang sama, ada dua subtipe dari hubungan ini: Komposisi - satu objek menciptakan objek lain dan masa hidup objek lain bergantung pada masa hidup penciptanya. Agregasi - suatu objek menerima tautan (penunjuk) ke objek lain selama proses konstruksi (dalam hal ini, umur objek lain tidak bergantung pada umur pembuatnya). Untuk pemahaman yang lebih baik, mari kita lihat contoh spesifik. Kami memiliki kelas mobil tertentu - Car , yang pada gilirannya memiliki bidang internal seperti - Engine dan daftar penumpang - List<Passenger> , ia juga memiliki metode untuk memulai pergerakan - startMoving() :
public class Car {

 private Engine engine;
 private List<Passenger> passengers;

 public Car(final List<Passenger> passengers) {
   this.engine = new Engine();
   this.passengers = passengers;
 }

 public void addPassenger(Passenger passenger) {
   passengers.add(passenger);
 }

 public void removePassengerByIndex(Long index) {
   passengers.remove(index);
 }

 public void startMoving() {
   engine.start();
   System.out.println("Машина начала своё движение");
   for (Passenger passenger : passengers) {
     System.out.println("В машине есть пассажир - " + passenger.getName());
   }
 }
}
Dalam hal ini Composition adalah hubungan antara Car dan Engine , karena performa mobil secara langsung bergantung pada keberadaan objek engine, karena jika engine = null , maka kita akan menerima NullPointerException . Pada gilirannya, sebuah mesin tidak dapat ada tanpa sebuah mesin (mengapa kita membutuhkan sebuah mesin tanpa sebuah mesin?) dan tidak dapat dimiliki oleh beberapa mesin pada satu waktu. Artinya jika kita menghapus objek Car maka tidak akan ada lagi referensi ke objek Engine dan akan segera dihapus oleh Garbage Collector . Seperti yang Anda lihat, hubungan ini sangat ketat (kuat). Agregasi adalah hubungan antara Mobil dan Penumpang , karena kinerja Mobil sama sekali tidak bergantung pada objek jenis Penumpang dan jumlahnya. Mereka dapat meninggalkan mobil - deletePassengerByIndex(Indeks panjang) atau memasukkan yang baru - addPassenger(Penumpang penumpang) , meskipun demikian, mobil akan tetap berfungsi dengan baik. Pada gilirannya, objek Passenger bisa ada tanpa objek Car . Seperti yang Anda pahami, ini adalah koneksi yang jauh lebih lemah daripada yang kita lihat di komposisi. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 3Namun bukan itu saja, suatu objek yang terhubung secara agregasi ke objek lain juga dapat memiliki koneksi tertentu dengan objek lain pada titik waktu yang sama. Misalnya, Anda, sebagai pelajar Java, terdaftar dalam kursus bahasa Inggris, OOP, dan logaritma pada waktu yang sama, namun pada saat yang sama Anda bukan bagian yang sangat penting dari kursus tersebut, yang tanpanya fungsi normal tidak mungkin dilakukan (seperti sebagai guru).

3. Pola GoF apa yang pernah Anda gunakan dalam praktiknya? Berikan contoh.

Saya sudah menjawab pertanyaan ini sebelumnya, jadi saya tinggalkan saja link analisisnya , lihat pertanyaan pertama. Saya juga menemukan artikel contekan yang bagus tentang pola desain, yang sangat saya sarankan untuk selalu Anda simpan.

4. Apa yang dimaksud dengan objek proxy? Berikan contoh

Proksi adalah pola desain struktural yang memungkinkan Anda mengganti objek pengganti khusus, atau dengan kata lain, objek proksi, dan bukan objek nyata. Objek proxy ini mencegat panggilan ke objek asli, memungkinkan beberapa logika dimasukkan sebelum atau setelah panggilan diteruskan ke objek asli. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 4Contoh penggunaan objek proxy:
  • Sebagai proxy jarak jauh - digunakan ketika kita membutuhkan objek jarak jauh (objek dalam ruang alamat berbeda) yang perlu direpresentasikan secara lokal. Dalam hal ini, proxy akan menangani pembuatan koneksi, pengkodean, decoding, dll., sedangkan klien akan menggunakannya seolah-olah itu adalah objek asli yang terletak di ruang lokal.

  • Sebagai proxy virtual - digunakan ketika objek yang membutuhkan banyak sumber daya. Dalam hal ini, objek proxy berfungsi sebagai sesuatu seperti gambar dari objek nyata yang sebenarnya belum ada. Ketika permintaan nyata (pemanggilan metode) dikirim ke objek ini, barulah objek asli dimuat dan metode dijalankan. Pendekatan ini juga disebut inisialisasi malas; ini bisa sangat mudah, karena dalam beberapa situasi objek asli mungkin tidak berguna, dan kemudian tidak ada biaya untuk membuatnya.

  • Sebagai proxy keamanan - digunakan ketika Anda perlu mengontrol akses ke beberapa objek berdasarkan hak klien. Artinya, jika klien dengan hak akses yang hilang mencoba mengakses objek asli, proxy akan mencegatnya dan tidak mengizinkannya.

Mari kita lihat contoh proxy virtual: Kami memiliki beberapa antarmuka pengendali:
public interface Processor {
 void process();
}
Implementasinya menggunakan terlalu banyak sumber daya, namun pada saat yang sama mungkin tidak digunakan setiap kali aplikasi diluncurkan:
public class HiperDifficultProcessor implements Processor {
 @Override
 public void process() {
   // некоторый сверхсложная обработка данных
 }
}
Kelas proksi:
public class HiperDifficultProcessorProxy implements Processor {
private HiperDifficultProcessor processor;

 @Override
 public void process() {
   if (processor == null) {
     processor = new HiperDifficultProcessor();
   }
   processor.process();
 }
}
Mari kita jalankan di main :
Processor processor = new HiperDifficultProcessorProxy();
// тут тяжеловсеного оригинального an object, ещё не сущетсвует
// но при этом есть an object, который его представляет и у которого можно вызывать его методы
processor.process(); // лишь теперь, an object оригинал был создан
Saya perhatikan bahwa banyak kerangka kerja menggunakan proxy, dan untuk Spring ini adalah pola kuncinya (Spring digabungkan dengan itu luar dan dalam). Baca lebih lanjut tentang pola ini di sini . Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 5

5. Inovasi apa saja yang diumumkan di Java 8?

Inovasi yang dibawa oleh Java 8 adalah sebagai berikut:
  • Antarmuka fungsional telah ditambahkan, baca tentang jenis binatang apa ini di sini .

  • Ekspresi Lambda, yang terkait erat dengan antarmuka fungsional, baca lebih lanjut tentang penggunaannya di sini .

  • Menambahkan Stream API untuk kemudahan pemrosesan pengumpulan data, baca selengkapnya di sini .

  • Menambahkan tautan ke metode .

  • Metode forEach() telah ditambahkan ke antarmuka Iterable .

  • Menambahkan API tanggal dan waktu baru dalam paket java.time , analisis terperinci di sini .

  • Peningkatan API Bersamaan .

  • Menambahkan kelas pembungkus Opsional , yang digunakan untuk menangani nilai null dengan benar, Anda dapat menemukan artikel bagus tentang topik ini di sini .

  • Menambahkan kemampuan antarmuka untuk menggunakan metode statis dan default (yang, pada dasarnya, membawa Java lebih dekat ke pewarisan berganda), detail selengkapnya di sini .

  • Menambahkan metode baru ke kelas Collection(removeIf(), spliterator()) .

  • Perbaikan kecil pada Java Core.

Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 6

6. Apa itu Kohesi Tinggi dan Kopling Rendah? Berikan contoh.

Kohesi Tinggi atau Kohesi Tinggi adalah konsep ketika suatu kelas tertentu mengandung unsur-unsur yang berkaitan erat satu sama lain dan digabungkan untuk tujuannya. Misalnya, semua metode di kelas Pengguna harus mewakili perilaku pengguna. Suatu kelas memiliki kohesi yang rendah jika mengandung elemen-elemen yang tidak berhubungan. Misalnya, kelas User berisi metode validasi alamat email:
public class User {
private String name;
private String email;

 public String getName() {
   return this.name;
 }

 public void setName(final String name) {
   this.name = name;
 }

 public String getEmail() {
   return this.email;
 }

 public void setEmail(final String email) {
   this.email = email;
 }

 public boolean isValidEmail() {
   // некоторая логика валидации емейла
 }
}
Kelas pengguna mungkin bertanggung jawab untuk menyimpan alamat email pengguna, tetapi tidak untuk memvalidasinya atau mengirim email. Oleh karena itu, untuk mencapai koherensi yang tinggi, kami memindahkan metode validasi ke kelas utilitas terpisah:
public class EmailUtil {
 public static boolean isValidEmail(String email) {
   // некоторая логика валидации емейла
 }
}
Dan kami menggunakannya sesuai kebutuhan (misalnya, sebelum menyimpan pengguna). Kopling Rendah atau Low Coupling adalah sebuah konsep yang menggambarkan rendahnya saling ketergantungan antar modul perangkat lunak. Pada dasarnya, saling ketergantungan berarti bahwa mengubah satu hal memerlukan perubahan yang lain. Dua kelas mempunyai kopling yang kuat (atau kopling ketat) jika keduanya berkerabat dekat. Misalnya, dua kelas konkrit yang menyimpan referensi satu sama lain dan memanggil metode masing-masing. Kelas yang digabungkan secara longgar lebih mudah untuk dikembangkan dan dipelihara. Karena keduanya independen satu sama lain, maka keduanya dapat dikembangkan dan diuji secara paralel. Selain itu, mereka dapat diubah dan diperbarui tanpa mempengaruhi satu sama lain. Mari kita lihat contoh kelas yang digabungkan secara kuat. Kami memiliki beberapa kelas siswa:
public class Student {
 private Long id;
 private String name;
 private List<Lesson> lesson;
}
Yang berisi daftar pelajaran:
public class Lesson {
 private Long id;
 private String name;
 private List<Student> students;
}
Setiap pelajaran berisi tautan ke siswa yang hadir. Cengkeramannya sangat kuat, bukan? Bagaimana cara menguranginya? Pertama, pastikan siswa tidak memiliki daftar mata pelajaran, tetapi daftar pengenal mereka:
public class Student {
 private Long id;
 private String name;
 private List<Long> lessonIds;
}
Kedua, kelas pelajaran tidak perlu mengetahui semua siswa, jadi mari kita hapus daftar mereka seluruhnya:
public class Lesson {
 private Long id;
 private String name;
}
Jadi semuanya menjadi lebih mudah, dan koneksi menjadi jauh lebih lemah, bukan begitu? Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 7

OOP

7. Bagaimana cara mengimplementasikan pewarisan berganda di Java?

Warisan berganda adalah fitur konsep berorientasi objek dimana suatu kelas dapat mewarisi properti dari lebih dari satu kelas induk. Masalah muncul ketika ada metode dengan tanda tangan yang sama di kelas super dan subkelas. Saat memanggil suatu metode, kompiler tidak dapat menentukan metode kelas mana yang harus dipanggil, dan bahkan saat memanggil metode kelas yang diutamakan. Oleh karena itu, Java tidak mendukung pewarisan berganda! Namun ada semacam celah, yang akan kita bicarakan selanjutnya. Seperti yang saya sebutkan sebelumnya, dengan dirilisnya Java 8, kemampuan untuk memiliki metode default ditambahkan ke interfaces . Jika kelas yang mengimplementasikan antarmuka tidak mengganti metode ini, maka implementasi default ini akan digunakan (tidak perlu mengganti metode default, seperti mengimplementasikan metode abstrak). Dalam hal ini, dimungkinkan untuk mengimplementasikan antarmuka yang berbeda dalam satu kelas dan menggunakan metode defaultnya. Mari kita lihat sebuah contoh. Kami memiliki beberapa antarmuka brosur, dengan metode fly() default :
public interface Flyer {
 default void fly() {
   System.out.println("Я лечу!!!");
 }
}
Antarmuka walker, dengan metode walk() default :
public interface Walker {
 default void walk() {
   System.out.println("Я хожу!!!");
 }
}
Antarmuka perenang, dengan metode swim() :
public interface Swimmer {
 default void swim() {
   System.out.println("Я плыву!!!");
 }
}
Nah, sekarang mari kita implementasikan semua ini dalam satu kelas bebek:
public class Duck implements Flyer, Swimmer, Walker {
}
Dan mari kita jalankan semua metode bebek kita:
Duck donald = new Duck();
donald.walk();
donald.fly();
donald.swim();
Di konsol kita akan menerima:
Aku pergi!!! Aku terbang!!! aku sedang berenang!!!
Ini berarti kita telah menggambarkan pewarisan berganda dengan benar, meskipun sebenarnya tidak demikian. Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 8Saya juga mencatat bahwa jika sebuah kelas mengimplementasikan antarmuka dengan metode default yang memiliki nama metode yang sama dan argumen yang sama dalam metode ini, maka kompiler akan mulai mengeluh tentang ketidakcocokan karena tidak memahami metode mana yang benar-benar perlu digunakan. Ada beberapa jalan keluar:
  • Ganti nama metode di antarmuka sehingga berbeda satu sama lain.
  • Timpa metode kontroversial tersebut di kelas implementasi.
  • Mewarisi dari kelas yang mengimplementasikan metode kontroversial ini (maka kelas Anda akan menggunakan implementasinya dengan tepat).

8. Apa perbedaan antara metode final, final, dan finalize()?

final adalah kata kunci yang digunakan untuk menempatkan batasan pada suatu kelas, metode, atau variabel, arti batasan:
  • Untuk variabel - setelah inisialisasi awal, variabel tidak dapat didefinisikan ulang.
  • Untuk suatu metode, metode tersebut tidak dapat ditimpa dalam subkelas (kelas penerus).
  • Untuk sebuah kelas - kelas tersebut tidak dapat diwarisi.
akhirnya adalah kata kunci sebelum blok kode, digunakan saat menangani pengecualian, bersamaan dengan blok coba , dan bersama-sama (atau bergantian) dengan blok catch. Kode dalam blok ini dieksekusi dalam hal apa pun, terlepas dari apakah pengecualian diberikan atau tidak. Di bagian artikel ini , pada pertanyaan 104, situasi luar biasa di mana blok ini tidak akan dieksekusi dibahas. finalize() adalah metode kelas Object , dipanggil sebelum setiap objek dihapus oleh pengumpul sampah, metode ini akan dipanggil (terakhir), dan digunakan untuk membersihkan sumber daya yang ditempati. Untuk informasi selengkapnya tentang metode kelas Object yang diwarisi setiap objek, lihat pertanyaan 11 di bagian artikel ini . Nah, di situlah kita akan mengakhiri hari ini. Sampai jumpa di bagian selanjutnya! Analisis tanya jawab dari wawancara untuk pengembang Java.  Bagian 14 - 9
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION