instanceof java list_Java:Instanceof和泛型
在查看通用數據結構中的值索引之前,我想看看它是否甚至已被參數化為類型this的實例。
但是當我這樣做時,Eclipse會抱怨:
@Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
這是錯誤消息:
Cannot perform instanceof check against type parameter E. Use instead its erasure Object since generic type information will be erased at runtime
有什么更好的方法呢?
錯誤消息說明了一切。在運行時,該類型已消失,無法對其進行檢查。
您可以通過為對象創建工廠來捕獲它,如下所示:
public static < T > MyObject< T > createMyObject(Class< T > type) {
return new MyObject< T >(type);
}
然后在對象的構造函數中存儲該類型,變量,以便您的方法如下所示:
if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass()))
{
return -1;
}
我不認為您想要Class.isAssignableFrom。
@Tom,我昨晚是從記憶中寫這本書的,我將其固定為實際上通過了課程(duh!),但否則,我不明白您為什么不想要它(也許今天早上我需要更多咖啡,我只在我的第一杯咖啡上)。
我和湯姆在一起。你能澄清一下嗎?使用isAssignableFrom()將是我的工作選擇。也許我錯過了什么?
@ luis,Toms評論可能意味著我應該使用isInstance()并傳遞實際的arg0參數。它具有避免空檢查的優點。
我有類似的情況,但我無法完全理解答案。你能為像我這樣的假人澄清一下嗎?
@RubensMariuzzo可能有幫助:ralfebert.de/blog/java/isassignablefrom的重要部分是:isAssignableFrom告訴您泛型T是否是實例arg0的超類。
@ Emerald214,您不需要擴展該類,但是該類具有靜態方法(這是靜態工廠模式javaworld.com/javaworld/jw-06-2001/j1-01-sintes2.html)
使用泛型進行運行時類型檢查的兩個選項:
選項1-破壞您的構造函數
假設您要覆蓋indexOf(...),并且只想檢查類型以提高性能,以免自己遍歷整個集合。
創建一個骯臟的構造函數,如下所示:
public MyCollection< T >(Class< T > t) {
this.t = t;
}
然后,您可以使用isAssignableFrom檢查類型。
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
每次實例化對象時,都必須重復一次:
new MyCollection(Apples.class);
您可能會認為這不值得。在ArrayList.indexOf(...)的實現中,它們不檢查類型是否匹配。
選項2-讓它失敗
如果您需要使用需要未知類型的抽象方法,那么您真正想要的只是讓編譯器停止對instanceof的抱怨。如果您有這樣的方法:
protected abstract void abstractMethod(T element);
您可以像這樣使用它:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
您正在將對象強制轉換為T(您的泛型類型),只是為了欺騙編譯器。您的強制轉換在運行時不執行任何操作,但是當您嘗試將錯誤類型的對象傳遞給抽象方法時,您仍然會收到ClassCastException。
注意1:如果您在抽象方法中執行其他未經檢查的強制轉換,則ClassCastExceptions將在此處被捕獲。那可能是好事也可能是壞事,因此請仔細考慮。
注意2:使用instanceof時,您將獲得免費的空檢查。由于您無法使用它,因此您可能需要裸手檢查null。
舊帖子,但是做普通instanceOf檢查的一種簡單方法。
public static < T > boolean isInstanceOf(Class< T > clazz, Class< T > targetClass) {
return clazz.isInstance(targetClass);
}
目前尚不清楚您在這里實際做出了什么貢獻。
如果您的類擴展了具有通用參數的類,則您還可以在運行時通過反射來獲取它,然后將其用于比較,即
class YourClass extends SomeOtherClass
{
private Class< ? > clazz;
public Class< ? > getParameterizedClass()
{
if(clazz == null)
{
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
clazz = (Class< ? >)pt.getActualTypeArguments()[0];
}
return clazz;
}
}
在上述情況下,在運行時將從getParameterizedClass()中獲取String.class并進行緩存,因此在進行多次檢查時不會有任何反射開銷。請注意,您可以從ParameterizedType.getActualTypeArguments()方法中通過索引獲取其他參數化類型。
我遇到了同樣的問題,這是我的解決方案(非常謙虛,@ george:這一次編譯并正在工作……)。
我的探針位于實現Observer的抽象類內部。
Observable可以通過Object類觸發update(...)方法,該方法可以是任何種類的Object。
我只想處理T類型的對象
解決方案是將類傳遞給構造函數,以便能夠在運行時比較類型。
public abstract class AbstractOne< T > implements Observer {
private Class< T > tClass;
public AbstractOne(Class< T > clazz) {
tClass = clazz;
}
@Override
public void update(Observable o, Object arg) {
if (tClass.isInstance(arg)) {
// Here I am, arg has the type T
foo((T) arg);
}
}
public abstract foo(T t);
}
對于實現,我們只需要將Class傳遞給構造函數
public class OneImpl extends AbstractOne {
public OneImpl() {
super(Rule.class);
}
@Override
public void foo(Rule t){
}
}
否則您可能會嘗試將E轉換為E失敗,例如
public int indexOf(Object arg0){
try{
E test=(E)arg0;
return doStuff(test);
}catch(ClassCastException e){
return -1;
}
}
+1實用的非工程化解決方案,可輕松進行檢查!我希望我能投票更多
這不會工作。 E在運行時被擦除,因此強制類型轉換不會失敗,您只會收到編譯器警告。
對象的運行時類型是要過濾的相對任意的條件。我建議遠離您的收藏夾。只需將您的集合委托給構造中傳遞的過濾器即可實現。
public interface FilterObject {
boolean isAllowed(Object obj);
}
public class FilterOptimizedList implements List {
private final FilterObject filter;
...
public FilterOptimizedList(FilterObject filter) {
if (filter == null) {
throw NullPointerException();
}
this.filter = filter;
}
...
public int indexOf(Object obj) {
if (!filter.isAllows(obj)) {
return -1;
}
...
}
...
}
final List longStrs = new FilterOptimizedList(
new FilterObject() { public boolean isAllowed(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
String str = (String)str;
return str.length() > = 4;
} else {
return false;
}
}}
);
(盡管如果您使用的是Comparator或類似版本,則可能要檢查實例類型。)
從技術上講,您不必這樣做,這就是泛型的重點,因此您可以進行編譯類型檢查:
public int indexOf(E arg0) {
...
}
但是如果您有一個類層次結構,那么@Override可能是一個問題。否則,請參見Yishai的答案。
是的,List接口要求該函數采用對象參數。
您實施清單?為什么不實施List ?
(例如,參見ArrayList的聲明:java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html)
@Rosarch:List接口的indexOf()方法不需要給定的參數與您要查找的對象具有相同的類型。它只是必須等于.equals(),并且不同類型的對象可以彼此等于.equals()。這與remove()方法的問題相同,請參見:stackoverflow.com/questions/104799/
[[[sheepishly]]]沒關系,我認為indexOf()要求E作為參數而不是Object。 (他們為什么這樣做?!?!)
@Jason基本上是因為它會破壞不需要有效類型轉換的完全有效的代碼。另外,由于泛型不是協變的,因此即使使用indexOf()實際上返回一個實數索引(對象),您也會陷入一些帶有類型參數的極端情況(例如,列表本身具有類型參數的列表)在列表中,但編譯器無法讓您看到它)。
總結
以上是生活随笔為你收集整理的instanceof java list_Java:Instanceof和泛型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python用于数据分析的案例_Pyth
- 下一篇: 病毒源代码Java_病毒代码_bat病毒