public class Hashing<Key, Elem>
我想检查Key是否为int,所以我将这些行放在构造函数中:
Key key = null;
if (!(key instanceof Integer)) {
throw new TypeOfKeyStillNotSupportedException();
}
但是,我这样创建一个:
tHash = new Hashing<Integer, Movie>(max);
该死的TypeOfKeyStillNotSupportedException()会弹出。为什么会发生这种情况?我该如何正确地做到这一点?
提前致谢。
编辑:已经发现问题是将密钥指定为null。现在的问题是:如何进行检查?
答案 0 :(得分:3)
null
不是instanceof
任何内容。由于类型擦除,无法在运行时直接检查Key
的类型。一种选择是让用户将Class<Key>
传递给构造函数,以便您可以检查:
public Hashing(Class<Key> keyType, ...) {
if (keyType != Integer.class) {
throw new TypeOfKeyStillNotSupportedException();
}
...
}
...
Hashing<Integer, Foo> hashing = new Hashing<Integer, Foo>(Integer.class, ...);
为了避免重复类型参数,您可以创建一个静态工厂方法:
public static <K, E> Hashing<K, E> create(Class<K> keyType, ...) {
return new Hashing<K, E>(keyType, ...);
}
...
Hashing<Integer, Foo> hashing = Hashing.create(Integer.class, ...);
答案 1 :(得分:2)
如果您的代码有“key = null;”在instanceof测试之前,必然会抛出异常。
原因是instancof运算符检查指向的对象类型的引用,而不是声明它的声明方式。
您可以尝试使用这个简单的示例并相应地删除注释以查看差异:
public static void main(String[] args) {
//Object obj = new Integer(9);
Object obj = null;
if (!(obj instanceof Integer))
System.out.println("Not Integer.");
else
System.out.println("Is Integer");
}
此外,您可以在此处找到更多详细信息:
http://download.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
希望有所帮助:)
Java Generics的全面展示:
class GenTest<Key extends Integer, Value>{
Key key;
Value val;
GenTest(Key key, Value val){
this.key = key;
this.val = val;
System.out.println("Key: " + key + " Value: " + val);
}
}
public class GenericRecap {
public static void main(String[] args) {
//Object obj = new Integer(9);
Object obj = null;
if (!(obj instanceof Integer))
System.out.println("Not Integer.");
else
System.out.println("Is Integer");
new GenTest<Integer, String>(9, "nine");
//new GenTest<String, String>("funny", "nine"); // In-Error
}
}
另请注意,通过使用“Key extends Integer”,如果传递的不是Integer的子类,则会在运行时抛出异常。此外,如果您正在使用和IDE检查它,它将标记为GenTest类中的“Type not within bound”。
Floats和Integer都继承自Number。因此,你可以'扩展数字'然后检查'instanceof Integer'或'instanceof Float',具体取决于你在代码中如何使用它。
希望有所帮助:)干杯!
答案 2 :(得分:2)
Java泛型是使用type erasure实现的:编译器在用于类型检查后会丢弃通用信息,因此在运行时,您的类实际上只是Hashing<Object, Object>
。这就是为什么你不能根据泛型类型进行运行时检查。
您可以向构造函数添加类型为Class<Key>
的参数,并且调用者必须为正用作键的类型传递正确的类对象。例如,在Hashing<Integer, String>
中,只接受Integer.class
作为该参数的值,您可以将其用于运行时类型检查。将键的类对象作为参数传递的要求使构造函数调用看起来有点尴尬。
答案 3 :(得分:0)
从您的示例中给出以下内容:
public class Hashing<K, E>
这没有任何意义:因为K
是一个Type
,可以在课程专业化时设置为任何内容。我将名称从Key
更改为K
,以消除您Key
未代表Type
的混淆。 Type
名称的一般标准是大多数时候使用单个字符。
K key = null;
if (!(key instanceof Integer))
{
throw new TypeOfKeyStillNotSupportedException();
}
如果您将其更改为
K key = null;
if (!(key instanceof K))
{
throw new TypeOfKeyStillNotSupportedException();
}
这将是一个更Generic
解决方案,但这没有任何意义,因为key
总是是K
key
不能null
,因为null
不属于任何Type
如果没有更多关于instanceof
支票周围环境的背景信息,我不知道你的意图是什么。
使用Type
检查Generic
的{{1}}是一种代码味道,无论如何都可能是错误的方法。
在此处查看instanceof
implementation如何处理此问题。
他们使用java.util.HashMap
的地方只有两个,而且这些地方都只接受instanceof
并且不属于类型安全。
答案 4 :(得分:0)
处理此问题的方法是显式测试null; e.g。
Key key = null;
if (key == null) {
throw new KeyIsNullException();
} else if (!(key instanceof Integer)) {
throw new TypeOfKeyStillNotSupportedException();
}
// ... or (for the literal minded) ...
if (key != null && !(key instanceof Integer)) {
throw new TypeOfKeyStillNotSupportedException();
}
为了记录,那些回复说这与类型擦除有关的人是不合适的。如果Key
是一个明确的类或接口,您将获得完全相同的行为。
(另一方面,如果代码说someObj instanceof Key
...由于类型擦除问题,那将是一个编译错误。)
答案 5 :(得分:0)
您需要一个isInstance方法,该方法是动态等效于instanceof
运算符。
例如,
Integer.class.isInstance(1); //return true
Integer.class.isInstance(null); //return false
修改强>:
如果要针对不同的类类型进行测试,请编写如下的实用程序方法:
static <T> boolean isInstance(Class<T> type, Object obj) {
return type.isInstance(obj);
}
例如,
Hashing.<String>isInstance(String.class, "hi"); // return true