17. Berikan contoh keberhasilan dan kegagalan penggunaan Opsional
Misalkan kita memiliki serangkaian nilai tertentu yang melaluinya kita melewati aliran tersebut, dan pada akhirnya kita mendapatkan beberapa Opsional sebagai hasilnya:Optional<String> stringOptional = Stream.of("a", "ab", "abc", "abcd")
.filter(str -> str.length() >= 3)
.findAny();
Kita, seperti yang diharapkan, perlu mendapatkan nilai dari Optional ini . Hanya menggunakan get() adalah cara yang buruk:
String result = stringOptional.get();
Tapi metode ini seharusnya mendapatkan nilai dari Opsional dan mengembalikannya kepada kami? Tentu saja ini benar, tetapi jika itu ada artinya. Nah, jika nilai dalam aliran berbeda, dan pada akhirnya kita menerima Optional kosong , ketika kita mencoba mengambil nilai darinya menggunakan metode get() , yang berikut akan muncul: Mana yang tidak bagus. Dalam hal ini, lebih baik menggunakan konstruksi berikut:
-
String result = null; if (stringOptional.isPresent()) { stringOptional.get(); }
Dalam hal ini, kami memeriksa untuk melihat apakah elemen tersebut ada di Optional . Jika tidak, string yang dihasilkan memiliki nilai lama.
-
String result = stringOptional.orElse("default value");
Dalam hal ini, kami menentukan beberapa nilai default, yang akan diberikan ke string yang dihasilkan jika Optional kosong .
-
String result = stringOptional.orElseThrow(() -> new CustomException());
Dalam hal ini, kami sendiri memberikan pengecualian ketika Optional kosong .
18. Apakah mungkin untuk mendeklarasikan metode utama sebagai metode final?
Ya, tentu saja, tidak ada yang menghalangi kami untuk mendeklarasikan metode main() sebagai final . Kompiler tidak akan menghasilkan kesalahan. Namun perlu diingat bahwa metode apa pun setelah dinyatakan final akan menjadi metode terakhir - tidak ditimpa. Meskipun demikian, siapa yang akan mendefinisikan ulang main ???19. Apakah mungkin mengimpor paket/kelas yang sama dua kali? Apa konsekuensinya?
Ya kamu bisa. Konsekuensi? Kami akan memiliki beberapa impor yang tidak perlu yang akan ditampilkan Intelijj IDEA sebagai abu-abu, yaitu. tidak terpakai.20. Apa itu Transmisi? Kapan kita bisa mendapatkan ClassCastException?
Casting, atau type casting , adalah proses mengubah satu tipe data ke tipe data lain: secara manual (casting implisit) atau otomatis (casting tipe eksplisit). Konversi otomatis dilakukan oleh kompiler, dan konversi manual dilakukan oleh pengembang. Jenis casting untuk primitif dan kelas agak berbeda, jadi kami akan mempertimbangkannya secara terpisah. Tipe primitif Contoh casting otomatis tipe primitif:int value = 17;
double convertedValue = value;
Seperti yang Anda lihat, tidak diperlukan manipulasi tambahan selain tanda = di sini. Contoh casting manual tipe primitif:
double value = 17.89;
int convertedValue = (int)value;
Dalam hal ini, kita dapat mengamati cast manual, yang diimplementasikan menggunakan (int) , di mana bagian setelah koma akan dibuang dan convertValue akan memiliki nilai - 17. Baca lebih lanjut tentang casting tipe primitif di artikel ini . Nah, sekarang mari beralih ke objek. Tipe referensi Untuk tipe referensi, transmisi otomatis dimungkinkan untuk kelas turunan ke kelas induk. Ini juga disebut polimorfisme . Katakanlah kita memiliki kelas Lion yang mewarisi dari kelas Cat . Dalam hal ini, konversi otomatis akan terlihat seperti ini:
Cat cat = new Lion();
Tetapi dengan pemeran eksplisit , semuanya menjadi lebih rumit, karena tidak ada fungsi untuk memotong kelebihan, seperti pada primitif. Dan hanya melakukan konversi eksplisit dari bentuk:
Lion lion= (Lion)new Cat();
Anda akan mendapatkan kesalahan: Faktanya, Anda dapat menambahkan metode ke kelas turunan Lion yang awalnya tidak ada di kelas Cat , lalu mencoba memanggilnya karena tipe objek Anda akan menjadi Lion . Ya, tidak ada logika dalam hal ini. Oleh karena itu, penyempitan tipe hanya mungkin terjadi ketika objek aslinya bertipe Lion tetapi kemudian dimasukkan ke kelas induk:
Lion lion = new Lion();
Cat cat = lion;
Lion newLion = (Lion)cat;
Selain itu, untuk keandalan yang lebih baik, direkomendasikan untuk mempersempit objek menggunakan konstruksi instanceOf :
if (cat instanceof Lion) {
newLion = (Lion)new Cat();
}
Baca lebih lanjut tentang tipe referensi gips di artikel ini . .
21. Mengapa kerangka kerja modern hanya menggunakan pengecualian yang tidak dicentang?
Saya rasa ini semua karena penanganan pengecualian yang dicentang masih berupa kode spageti yang diulangi di mana-mana, tetapi tidak terlalu diperlukan di semua kasus. Dalam kasus seperti itu, lebih mudah untuk melakukan pemrosesan di dalam kerangka kerja, agar tidak sekali lagi mengalihkan tanggung jawab ini ke pundak pengembang. Ya, tentu saja, situasi darurat mungkin muncul, tetapi pengecualian yang tidak dicentang ini dapat ditangani dengan cara yang lebih mudah, tanpa mengganggu pemrosesan dalam try-catch dan tanpa meneruskannya lebih jauh melalui metode. Cukup dengan mengubah pengecualian menjadi beberapa respons HTTP di pengecualianHandler .22. Apa yang dimaksud dengan impor statis?
Saat menggunakan data statis (metode, variabel), Anda tidak dapat membuat objek itu sendiri, tetapi melakukannya dengan nama kelas, tetapi meskipun demikian kita memerlukan referensi ke kelas tersebut. Semuanya sederhana dengan itu: ditambahkan menggunakan impor biasa. Tetapi bagaimana jika kita menggunakan metode statis tanpa menulis nama kelas, seolah-olah itu adalah metode statis dari kelas saat ini? Hal ini dimungkinkan dengan impor statis! Dalam hal ini, kita harus menulis impor statis dan link ke metode tersebut. Seperti ini misalnya metode statis kelas Math untuk menghitung nilai kosinus:import static java.lang.Math.cos;
Hasilnya, kita dapat menggunakan metode ini tanpa menentukan nama kelas:
double result = cos(60);
Kita juga dapat memuat semua metode statis suatu kelas sekaligus menggunakan impor statis:
import static java.lang.Math.*;
23. Apa hubungan antara metode hashCode() dan sama dengan()?
Menurut Oracle , aturannya adalah: Jika dua objek sama (yaitu metode sama dengan() mengembalikan true ), keduanya harus memiliki kode hash yang sama. Pada saat yang sama, jangan lupa bahwa dua objek berbeda mungkin memiliki kode hash yang sama. Untuk memahami mengapa sama dengan() dan kode hash() selalu diganti secara berpasangan, pertimbangkan kasus berikut:-
Kedua metode tersebut ditimpa.
Dalam hal ini, dua objek berbeda dengan status internal yang sama akan mengembalikan equal() - true , sedangkan hashCode() keduanya akan mengembalikan angka yang sama.
Ternyata semuanya baik-baik saja, karena aturannya dipatuhi.
-
Kedua metode tersebut tidak dapat dikesampingkan.
Dalam hal ini, dua objek berbeda dengan status internal yang sama akan mengembalikan false ketika sama dengan() , karena perbandingannya dilakukan dengan referensi melalui operator == .
Metode hashCode() juga akan mengembalikan nilai yang berbeda (kemungkinan besar) karena menghasilkan nilai konversi dari alamat lokasi memori. Namun untuk objek yang sama nilainya akan sama, seperti halnya sama dengan() dalam hal ini akan mengembalikan nilai true hanya ketika referensi menunjuk ke objek yang sama.
Ternyata dalam hal ini semuanya baik-baik saja dan aturannya terpenuhi.
-
Diganti sama dengan() , bukan ditimpa hashCode() .
Dalam hal ini, untuk dua objek berbeda dengan status internal yang sama, equal() akan mengembalikan true , dan hashCode() (kemungkinan besar) akan mengembalikan nilai yang berbeda.
Ini merupakan pelanggaran aturan, jadi tidak disarankan untuk melakukan hal ini.
-
sama dengan() tidak diganti , kode hash() diganti .
Dalam hal ini, untuk dua objek berbeda dengan status internal yang sama, sama dengan() akan mengembalikan false dan hashCode() akan mengembalikan nilai yang sama.
Ada pelanggaran aturan, sehingga pendekatannya salah.
24. Kapan kelas BufferedInputStream dan BufferedOutputStream digunakan?
InputStream digunakan untuk membaca data byte demi byte dari beberapa sumber daya, dan OutputStream digunakan untuk menulis data byte demi byte. Namun operasi byte-byte bisa sangat merepotkan dan memerlukan pemrosesan tambahan (agar dapat membaca/menulis teks secara normal). Sebenarnya, untuk menyederhanakan catatan byte tersebut, BufferedOutputStream diperkenalkan , dan BufferedInputStream diperkenalkan untuk membaca . Kelas-kelas ini tidak lebih dari buffer yang mengumpulkan data, memungkinkan Anda bekerja dengan data bukan byte demi byte, tetapi seluruh paket data (array). Saat dibuat, BufferedInputStream memasukkan ke dalam konstruktornya sebuah instance dari tipe InputStream , dari mana data dibaca:BufferedInputStream bufferedInputStream = new BufferedInputStream(System.in);
byte[] arr = new byte[100];
bufferedInputStream.read(arr);
System.in adalah objek InputStream yang membaca data dari konsol. Artinya, dengan menggunakan objek BufferedInputStream ini , kita dapat membaca data dari InputStream dengan menuliskannya ke array yang diteruskan. Ini ternyata menjadi semacam pembungkus kelas InputStream . Array arr dari contoh ini adalah array yang menerima data dari BufferedInputStream . Itu, pada gilirannya, membaca data dari InputStream dengan array lain, yang secara default berukuran 2048 byte. Hal yang sama berlaku untuk BufferedOutputStream : sebuah instance dari tipe OutputStream harus diteruskan ke konstruktor , ke mana kita akan menulis data di seluruh array:
byte[] arr = "Hello world!!!".getBytes();
BufferedOutputStream bufferedInputStream = new BufferedOutputStream(System.out);
bufferedInputStream.write(arr);
bufferedInputStream.flush();
System.out adalah objek OutputStream yang menulis data ke konsol. Metode flush() mengirimkan data dari BufferedOutputStream ke OutputStream , membuang BufferedOutputStream dalam prosesnya . Tanpa metode ini, tidak ada yang akan direkam. Dan mirip dengan contoh sebelumnya: arr adalah array tempat data ditulis ke BufferedOutputStream . Dari sana mereka ditulis ke OutputStream dalam array berbeda, yang secara default berukuran 512 byte. Baca lebih lanjut tentang kedua kelas ini di artikel .
25. Apa perbedaan antara kelas java.util.Collection dan java.util.Collections?
Koleksi adalah antarmuka yang merupakan kepala hierarki koleksi. Ini memperkenalkan kelas yang memungkinkan Anda membuat, memuat, dan memodifikasi seluruh kelompok objek. Ada banyak metode yang disediakan untuk ini, seperti add() , hapus() , berisi() dan lain-lain. Antarmuka utama kelas Koleksi :-
Himpunan adalah antarmuka yang mendeskripsikan himpunan yang berisi elemen unik yang tidak berurutan (tidak berulang).
-
Daftar adalah antarmuka yang menggambarkan struktur data yang menyimpan urutan objek yang diurutkan. Objek-objek ini menerima indeks (angka) mereka sendiri, yang dengannya Anda dapat berinteraksi dengannya: mengambil, menghapus, mengubah, menimpa.
-
Antrian merupakan antarmuka yang menggambarkan suatu struktur data dengan elemen penyimpanan berupa antrian yang mengikuti aturan - FIFO - First In First Out .
-
addAll(Collection<? super T> collection, T...element) - menambahkan elemen tipe T yang diteruskan ke collection .
-
copy(List<? super T> dest, List<? extends T> src) - menyalin semua elemen dari daftar src ke daftar di dest .
-
blankList() - mengembalikan daftar kosong.
-
max(Collection<? extends T> collection, Comparator<? super T> comp) - Mengembalikan elemen maksimum dari koleksi tertentu sesuai dengan urutan yang ditentukan oleh komparator yang ditentukan.
-
unmodifiedList(List<? extends T> list) - mengembalikan representasi daftar yang diteruskan yang tidak dapat dimodifikasi.
GO TO FULL VERSION