Saya melakukan ulasan kode untuk kolega saya dua hari yang lalu. Saya merasa bahwa saya tidak memiliki pemahaman yang baik tentang java generik, jadi saya mengeluarkan buku "Efektif Java" 1 dan kemudian melihat bab -bab yang relevan. Di bagian 24: Hilangkan bagian Peringatan yang Tidak Dicentang, penulis menggunakan metode publik <t> t [] toarray (t [] a) di kelas ArrayList sebagai contoh untuk menggambarkan cara menggunakan anotasi @suppresswarnings untuk variabel.
ArrayList adalah kelas generik, yang dinyatakan seperti ini:
Javapublic Class ArrayList <E> Memperluas Daftar Abstrak <E> Menerapkan Daftar <E>, RandomAccess, CLONABLE, JAVA.IO.Serializable
Metode ToArray (T [] A) dari kelas ini adalah metode generik, yang dinyatakan dan diimplementasikan seperti ini:
@SuppressWarnings ("Uncecked") Public <t> t [] toarray (t [] a) {if (a.length <size) // Buat array baru jenis runtime A, tetapi konten saya: pengembalian (t []) array. ukuran) a [size] = null; return a;} Metode ini sebenarnya dinyatakan dalam antarmuka koleksi. Karena kami sering menggunakannya melalui Daftar Array, kami akan menggunakan ArrayList sebagai contoh di sini.
1 Mengapa dinyatakan sebagai tipe yang berbeda?
Pertanyaan saya adalah: mengapa metode ini menggunakan tipe t alih -alih tipe E arraylist? Yaitu, mengapa metode ini tidak dinyatakan seperti ini:
Javapublic e [] toarray (e [] a);
Jika jenisnya sama, kesalahan tipe parameter dapat ditemukan selama kompilasi. Jika jenisnya berbeda, mudah untuk menghasilkan kesalahan runtime. Misalnya, kode berikut:
// Buat ArrayListList <String> strlist = ArrayList baru <string> (); strlist.add ("ABC"); strlist.add ("xyz"); // Konversi strlist saat ini menjadi array angka. Perhatikan bahwa tidak ada kesalahan kompilasi dalam pernyataan berikut. Angka [] numArray = strlist.toArray (nomor baru [0]); Jalankan kode di atas dan baris 6 akan melempar pengecualian java.lang.arraystoreexception.
Jika metode ToArray menggunakan Tipe E, Pernyataan 2 akan menghasilkan kesalahan kompilasi. Kesalahan kompilasi lebih ramah daripada kesalahan runtime. Selain itu, tujuan utama generik adalah untuk menghilangkan kesalahan konversi tipe (ClassCastException) selama kompilasi. Metode ini sebaliknya. Apakah ini bug besar? Saya telah menemukan bug Java, tapi saya masih tidak percaya.
Setelah memeriksa internet, masalah ini telah dibahas berkali -kali 2, 3, 4.
2 dapat meningkatkan fleksibilitas
Deklarasi ini lebih fleksibel dan dapat mengubah elemen dalam daftar saat ini menjadi berbagai jenis yang lebih umum. Misalnya, jenis daftar saat ini adalah integer, dan kami dapat mengubah elemennya menjadi array angka.
Daftar <Integer> intlist = ArrayList baru <integer> (); intlist.add (1); intlist.add (2); angka [] numArray = intlist.toArray (nomor baru [0]);
Jika metode ini dinyatakan sebagai tipe E, kode di atas akan memiliki kesalahan kompilasi. Tampaknya akan lebih tepat untuk menyatakan metode sebagai berikut:
Javapublic <t super e> t [] toarray (t [] a);
Namun, sintaksis seperti <t super e> tidak ada di java. Dan bahkan jika itu ada, itu tidak berhasil untuk array. Ini juga karena alasan ini bahwa ketika menggunakan metode ini, bahkan jika T adalah kelas induk dari E, atau T sama dengan E, java.lang.arraystoreException 5, 6, 7 tidak dapat sepenuhnya dihindari. Silakan lihat dua kode berikut. Dalam kode pertama, T adalah kelas induk dari E, dan dalam kode kedua, t sama dengan E. Kedua bagian pengecualian kode.
Kode 1:
Daftar <Integer> intlist = ArrayList baru <Integer> (); intlist.add (1); intlist.add (2); Float [] floatArray = float baru [2]; // float adalah subkelas angka, jadi float [] adalah subclass dari angka [] angka [] numArray = floatarray; // pernyataan berikut akan melempar pengecualian arraystoreException numArray = intlist.toArray (numArray);
Kode 2:
Daftar <number> intlist = ArrayList baru <number> (); // Jenis daftar adalah nomor. Tetapi angka adalah kelas abstrak, dan hanya dapat menyimpan contoh subclass intlist.add (integer baru ()); intlist.add (integer baru ()); Float [] floatArray = new float []; // float adalah subclass dari angka, jadi float [] adalah subclass dari angka [] angka [] numArray = floatarray; // pernyataan berikut akan melempar pengecualian arraystoreException numArray = intlist.toArray (numArray);
Pengecualian di atas semua disebabkan oleh fakta ini: jika a adalah kelas induk B, maka a [] adalah kelas induk dari b []. Semua kelas di Java mewarisi dari objek, dan objek [] adalah kelas induk dari semua array.
Posting 8 ini memberikan contoh, menunjukkan bahwa bahkan jika jenis metode ini dinyatakan sebagai E, arrayStoreEexception tidak dapat dihindari.
Pengecualian ini juga disebutkan dalam dokumentasi untuk metode ini:
ArrayStoreEexception Jika jenis runtime dari array yang ditentukan bukan supertype dari jenis runtime dari setiap elemen dalam daftar ini.
3 Ini bisa kompatibel dengan versi sebelum Java 1.5
Metode ini muncul sebelum pengenalan obat generik di Java (generik diperkenalkan di JDK1.5). Itu dinyatakan pada waktu itu:
Objek javapublic [] toarray (objek [] a)
Setelah obat generik muncul, banyak kelas dan metode menjadi generik. Metode ini juga menyatakannya seperti ini:
Javapublic <t> t [] toarray (t [] a)
Deklarasi ini kompatibel dengan versi sebelum Java 1.5.
4 Beberapa kata lagi
Metode ini membutuhkan parameter array. Jika panjang array ini lebih besar dari atau sama dengan ukuran daftar saat ini, elemen -elemen dalam daftar akan disimpan dalam array; Jika panjang array ini kurang dari ukuran daftar saat ini, array baru akan dibuat dan elemen -elemen dalam daftar saat ini akan disimpan dalam array yang baru dibuat. Untuk meningkatkan efisiensi, jika memungkinkan, panjang array yang ditularkan harus lebih besar dari atau sama dengan ukuran daftar untuk menghindari membuat array baru dengan metode ini.
Daftar <Integer> intlist = ArrayList baru <Integer> (); intlist.add (); intlist.add (); // paste dalam array, panjangnya adalah angka [] numArray = intlist.toArray (nomor baru []); // Pernyataan // Tempel dalam array, panjangnya sama dengan panjang nomor intlist [] numArray = intlist.toArray (nomor baru [intlist.size ()]); //Penyataan
Selain itu, array sebagai parameter tidak dapat menjadi nol, jika tidak nullpointerException akan dilemparkan.
Catatan kaki:
1
Java yang efektif (edisi ke -2)
2
Link
3
Link
4
Link
5
Link
6
Link
7
Link
8
Link
9
Link
10
Link
Dibuat: 2016-04-06 Rabu 21:14
Emacs 24.5.1 (mode org 8.2.10)
Mengesahkan
Konten di atas adalah alasan mengapa jenis parameter dari Java ArrayList.toArray (T []) yang diperkenalkan kepada Anda oleh editor adalah T alih -alih E. Saya harap ini akan membantu semua orang!