[英]Java syntax: public class Me extends Thing<String,Integer,Character>
免責聲明 :我是Java泛型和集合的新手。
背景 :我在這里和這里都研究了Java泛型的基礎知識。 現在,我試圖了解它們如何應用於Hadoop的Mapper ( public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>
)
問題 :直到今天,我僅在類定義中看到占位符 ( public class OrderedPair<K,V> implements Pair<K,V>
),而不是具體的類( public class Me extends Thing<String,Integer,Character>
)。
問題 :總的來說,如果我有這個...
public class Me extends Thing<String,Integer,Character>
...“擴展Thing<String,Integer,Character>
”是什么意思? 看來我在“擴展” Thing,即Me子類繼承了Thing超類的方法。 那繼承與Thing<String,String,String>
是否不同?
說明 :換句話說,擴展沒有泛型的類(例如, public class X extends Y
)和有泛型( public class X extends Y<a,b,c>
)之間的區別是什么?
通用類可以具有與之一起使用的不同類型(實例化它的對象時,可以選擇使用哪種類型)。 如果您擴展通用類並在其中放置具體類型,就像您在此處所做的那樣: public class Me extends Thing<String,Integer,Character>
,這意味着Me正在擴展Thing,但是Thing現在不再是通用的,因為它已經綁定到給定的類型。
以前,您可以將Thing實例化為:
Thing<String, Character, Integer> myThing = new Thing<>();
但我現在已受約束,您不能再為其選擇類型。
Me myMe = new Me();
您還可以使用實際的通用類型擴展Thing,因此您的Me類仍然是通用的。
public class <T, K, V> Me extends Thing<T, K, V>
...
// init with
Me<String, Character, Integer> myMe = new Me<>();
這樣,您可以在任何給定的通用類型下初始化Me,並將其傳遞給通用Thing。
您也可以部分完成。 因此,Thing的某些類型是固定的,在實例化Me時可以自由選擇。
public class <T> Me extends Thing<String, T, String>
...
// init with
Me<String> myMe = new Me<>();
擴展具有泛型類型的類時,可以選擇指定子類將在其下工作的類型。 例如, class MyList extends ArrayList<String>
將具有ArrayList
方法,但特定於字符串。
以同樣的方式,在擴展Mapper
,需要指定映射器將要處理的參數類型。 您可以通過提供Mapper
聲明的類型參數來實現。
澄清:換句話說,在不使用泛型的情況下擴展類(例如,公共類X擴展Y)與在泛型中進行
public class X extends Y<a,b,c>
(public class X extends Y<a,b,c>
)之間有什么區別?
區別在於,在第二種情況(泛型類)中,如果要編譯良好,則必須遵守泛型類指定的類型的約束,否則應聲明原始子類。
通常,由通用類指定的類型由其方法使用。
因此正確定義它們很重要。
您主要有3種情況。
采取此通用類聲明,該聲明指定3個參數,並在myMethod()
方法中使用它們:
public class Y <A extends AClass,B extends BClass, C extends CClass> {
public void myMethod(A a, B b, C c){
...
}
}
1)您的子類是原始類:
public class Z extends Y {
....
}
在這種情況下,它可以編譯正常但帶有警告。
您將失去泛型方法調用的好處。 編譯器將考慮具有此簽名的Z
方法:
public void myMethod(Object a, Object b, Object c){
...
}
2)您的子類是通用的兼容子類:
public class Z extends Y<ASubClass,BSubClass,CSubClass> {
....
}
編譯器將考慮具有此簽名的Z
方法:
public void myMethod(ASubClass a, BSubClass b, CSubClass c){
...
}
3)您的子類是泛型類,但不符合父類指定的參數,因此會出現編譯錯誤。
public class Z extends Y<BSubClass,ASubClass,CSubClass> {
....
}
如果超類型使用泛型,那么與任何泛型類型一樣,在沒有泛型參數的情況下引用它是使用原始類型的嚴重錯誤。 您必須為通用類型中的每個類型變量使用通用類型變量或具體類型。 例如,變量將像
Thing<String, Integer, Character> thing = new Thing<>();
自然不同於
Thing<String, String, String> thing = ...
因為它處理不同的類型!
繼承同樣適用。 在您的情況下,您將類型參數鎖定為具體類型。
public class SomeThing extends Thing<String, Integer, Character> { ...
鎖定SomeThing
可以處理的類型,因此SomeThing
實際上不是泛型類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.