Ada's diskusi yang baik dari obat Generik dan apa yang mereka benar-benar lakukan di belakang layar atas pada pertanyaan, sehingga kita semua tahu bahwa Vektor<int[]>
adalah vektor dari integer array, dan HashTable<String, Orang>
ini adalah tabel dan kunci string dan nilai-nilai Seseorang.
Namun, apa tunggul saya adalah penggunaan Kelas<>
.
Jawa kelas Kelas
seharusnya juga mengambil nama template, (atau jadi saya'm diberitahu oleh kuning garis bawahi di eclipse). Saya don't mengerti apa yang saya harus menempatkan di sana. Inti dari Kelas
objek adalah ketika anda don't sepenuhnya memiliki informasi tentang suatu objek, untuk refleksi dan semacamnya. Mengapa hal itu membuat saya menentukan kelas Kelas
objek yang akan tahan? Saya jelas don't tahu, atau saya tidak't akan menggunakan Kelas
objek, saya akan menggunakan satu tertentu.
Semua yang kita tahu adalah "Semua contoh dari setiap kelas saham yang sama java.lang.Class objek yang bertipe kelas"
e.g)
Student a = new Student();
Student b = new Student();
Maka a.getClass() == b.getClass()
adalah benar.
Sekarang asumsikan
Teacher t = new Teacher();
tanpa obat generik di bawah ini adalah mungkin.
Class studentClassRef = t.getClass();
Tapi ini adalah salah sekarang ..?
e.g) public void printStudentClassInfo(Kelas studentClassRef) {}
bisa disebut dengan Teacher.class
Hal ini dapat dihindari dengan menggunakan obat generik.
Class<Student> studentClassRef = t.getClass(); //Compilation error.
Sekarang apa yang T ?? T adalah tipe parameter (disebut juga tipe variabel); dibatasi oleh kurung sudut (<>), berikut nama kelas.
T hanya simbol, seperti nama variabel (dapat berupa nama) menyatakan selama penulisan file kelas. Kemudian yang T akan diganti dengan
valid nama Kelas selama inisialisasi (HashMap<String> peta = new HashMap<String>();
)
e.g) nama kelas<T1, T2, ..., Tn>
Jadi Kelas<T>
mewakili suatu kelas objek dari kelas tertentu jenis 'T
'.
Asumsikan bahwa anda metode kelas yang telah bekerja dengan yang tidak diketahui jenis parameter seperti di bawah ini
/**
* Generic version of the Car class.
* @param <T> the type of the value
*/
public class Car<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Di sini T dapat digunakan sebagai String
tipe CarName
ATAU T dapat digunakan sebagai Integer
tipe modelNumber,
ATAU T dapat digunakan sebagai Objek
tipe valid mobil contoh.
Sekarang di sini di atas adalah sederhana POJO yang dapat digunakan secara berbeda pada saat runtime.
Koleksi e.g) Daftar, Mengatur, dan Hashmap adalah contoh terbaik yang akan bekerja dengan benda-benda yang berbeda sesuai deklarasi T, tapi setelah kami dinyatakan T sebagai String
e.g) HashMap<String> peta = new HashMap<String>();
Maka hanya akan menerima String Kelas contoh benda-benda.
Generic Metode
Generic metode ini adalah metode yang memperkenalkan mereka sendiri jenis parameter. Ini adalah sama untuk menyatakan jenis generik, tetapi jenis parameter's lingkup terbatas pada metode di mana ia menyatakan. Statik dan non-statik generik metode yang diizinkan, serta generik kelas konstruktor.
Sintaks untuk metode generik termasuk jenis parameter, dalam kurung sudut, dan muncul sebelum metode's jenis kembali. Untuk generic metode, jenis bagian parameter harus muncul sebelum metode's jenis kembali.
class Util {
// Generic static method
public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
}
Berikut <K, V, Z, Y>
adalah deklarasi dari jenis yang digunakan dalam metode argumen yang harus sebelum kembali jenis yang boolean
di sini.
Di bawah; deklarasi tipe <T>
tidak diperlukan pada metode tingkat, karena sudah dideklarasikan di tingkat kelas.
class MyClass<T> {
private T myMethod(T a){
return a;
}
}
Tapi di bawah ini adalah salah karena tingkat kelas jenis parameter K, V, Z, dan Y tidak dapat digunakan dalam konteks statis (static method di sini).
class Util <K, V, Z, Y>{
// Generic static method
public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
LAINNYA VALID SKENARIO
class MyClass<T> {
//Type declaration <T> already done at class level
private T myMethod(T a){
return a;
}
//<T> is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass<T>.
private <T> T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass<String> obj= new MyClass<String>();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private <T> T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass<String> o= new MyClass<String>();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since <T> is undefined within this method;
// And MyClass<T> don't have impact here
private <T> T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class<T> a :: a is Class object of type T
//<T> is overriding of class level type declaration;
private <T> Class<T> myMethod4(Class<T> a){
return a;
}
}
Dan akhirnya metode Statis selalu membutuhkan eksplisit <T>
deklarasi; Itu tidak berasal dari tingkat kelas Kelas<T>
. Hal ini karena tingkat Kelas T terikat dengan contoh.
Baca juga Pembatasan pada obat Generik
Menggunakan generified versi dari kelas Kelas yang memungkinkan anda, antara lain, untuk menulis hal-hal seperti
Class<? extends Collection> someCollectionClass = someMethod();
dan kemudian anda dapat yakin bahwa objek Kelas anda menerima meluas Koleksi
, dan sebuah instance dari kelas ini akan (setidaknya) Koleksi.
Dari Jawa Dokumentasi:
[...] Lebih mengejutkan, kelas Kelas telah generified. Kelas literal sekarang berfungsi sebagai jenis token, menyediakan kedua run-time dan waktu kompilasi jenis informasi. Hal ini memungkinkan gaya statis pabrik-pabrik yang dicontohkan oleh getAnnotation metode baru AnnotatedElement antarmuka:
<T extends Annotation> T getAnnotation(Class<T> annotationType);
Ini adalah metode generik. Hal ini menyimpulkan nilai parameter jenis T dari argumen, dan mengembalikan sesuai contoh T, seperti yang digambarkan oleh cuplikan berikut:
Author a = Othello.class.getAnnotation(Author.class);
Sebelum obat generik, anda akan memiliki untuk cor hasilnya kepada Penulis. Juga anda akan memiliki tidak ada cara untuk membuat compiler memeriksa bahwa sebenarnya parameter yang diwakili sebuah subclass dari Penjelasan. [...]
Yah, aku tidak pernah harus menggunakan hal-hal seperti ini. Siapa saja?
Sebagai jawaban lain menunjukkan, ada banyak alasan yang baik mengapa hal ini kelas
dibuat generik. Namun ada banyak kali bahwa anda don't memiliki cara untuk mengetahui jenis generik untuk menggunakan dengan Kelas<T>
. Dalam kasus ini, anda dapat mengabaikan kuning gerhana peringatan atau anda bisa menggunakan Kelas<?>
... Yang's bagaimana saya melakukannya ;)
Berikut di @Kire Haglin's jawaban, contoh lebih lanjut dari obat generik metode dapat dilihat di dokumentasi untuk JAXB unmarshalling:
public <T> T unmarshal( Class<T> docClass, InputStream inputStream )
throws JAXBException {
String packageName = docClass.getPackage().getName();
JAXBContext jc = JAXBContext.newInstance( packageName );
Unmarshaller u = jc.createUnmarshaller();
JAXBElement<T> doc = (JAXBElement<T>)u.unmarshal( inputStream );
return doc.getValue();
}
Hal ini memungkinkan unmarshal
untuk kembali dokumen yang sewenang-wenang JAXB konten jenis pohon.
Di jawa <T>
berarti kelas Generik. Kelas Generik adalah sebuah kelas yang dapat bekerja pada setiap tipe tipe data atau dalam kata lain kita dapat mengatakan itu adalah tipe data yang independen.
public class Shape<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Mana T berarti jenis. Sekarang ketika anda membuat contoh dari Bentuk ini kelas anda akan perlu untuk memberitahu compiler untuk apa data jenis ini akan bekerja pada.
Contoh:
Shape<Integer> s1 = new Shape();
Shape<String> s2 = new Shape();
Bilangan bulat jenis dan String juga jenis.
<T>
khusus singkatan jenis generik. Menurut Jawa Docs - jenis generik generik kelas atau antarmuka yang parameter lebih dari jenis.
Anda seringkali ingin menggunakan wildcard dengan Kelas
. Misalnya, Kelas<? meluas JComponent>
, akan memungkinkan anda untuk menentukan bahwa kelas adalah beberapa subclass dari JComponent. Jika anda've diambil
Kelasinstance dari Kelas.forName
, maka anda dapat menggunakan Kelas.asSubclass
untuk melakukan cast sebelum mencoba, mengatakan, membangun sebuah instance.
Hanya untuk membuang dalam contoh lain, versi generik dari Kelas (Kelas
public static <T extends Enum<T>>Optional<T> optionalFromString(
@NotNull Class<T> clazz,
String name
) {
return Optional<T> opt = Optional.ofNullable(name)
.map(String::trim)
.filter(StringUtils::isNotBlank)
.map(String::toUpperCase)
.flatMap(n -> {
try {
return Optional.of(Enum.valueOf(clazz, n));
} catch (Exception e) {
return Optional.empty();
}
});
}
Hal ini membingungkan pada awalnya. Tetapi hal ini membantu dalam situasi di bawah ini :
class SomeAction implements Action {
}
// Later in the code.
Class<action> actionClass = Class.forName("SomeAction");
Action action = actionClass.newInstance();
// Notice you get an Action instance, there was no need to cast.
Hanya menggunakan daging sapi kelas:
public <T> T beefmarshal( Class<beef> beefClass, InputBeef inputBeef )
throws JAXBException {
String packageName = docClass.getPackage().getBeef();
JAXBContext beef = JAXBContext.newInstance( packageName );
Unmarshaller u = beef.createBeef();
JAXBElement<T> doc = (JAXBElement<T>)u.beefmarshal( inputBeef );
return doc.getBeef();
}