[英]Java: Check if a generic is an int
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 的密钥。 现在的问题是:如何进行检查?
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, ...);
为了避免重复 arguments 类型,您可以创建 static 工厂方法:
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, ...);
如果您的代码有“key = null;” 在 instanceof 测试之前,必然会抛出异常。
原因是 instancof 运算符检查指向的 object 类型的引用,而不是它的声明方式。
您可以尝试使用这个简单的示例并相应地删除注释以查看差异:
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 Class 的“类型不在范围内”。
浮点数和 Integer 都继承自 Number。 因此,您可以“扩展 Number”,然后根据您想在代码中使用它的方式检查“instanceof Integer”或“instanceof Float”。
希望它有所帮助:) 干杯!
Java generics 是使用类型擦除实现的:通用信息在用于类型检查后被编译器丢弃,因此在运行时您的 class 实际上只是Hashing<Object, Object>
这就是为什么您不能基于泛型类型进行运行时检查的原因。
您可以向构造函数添加Class<Key>
类型的参数,调用者必须为用作键的类型传递正确的 class object。 例如,在Hashing<Integer, String>
中,只有Integer.class
将被接受为该参数的值,您可以将其用于运行时类型检查。 但是,将密钥的 class object 作为参数传递的要求使得构造函数调用看起来有点尴尬。
鉴于您的示例中的以下内容:
public class Hashing<K, E>
这是没有意义的:因为K
是一个Type
,当 class 被专门化时,它可以设置为任何东西。 我将名称从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
检查的上下文,我不知道您的意图是什么。
用instanceof
检查Generic
的Type
是一种代码味道,无论如何都可能是错误的方法。
看这里java.util.HashMap
实现如何处理这个问题。
他们只有两个地方使用instanceof
并且都是遗留方法,只接受Object
并且不是类型安全的。
处理这种情况的方法是显式测试 null; 例如
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
是明确的 class 或接口,您将获得完全相同的行为。
(另一方面,如果代码说someObj instanceof Key
... 由于类型擦除问题,那将是编译错误。)
您需要一个isInstance方法,它是instanceof
运算符的动态等效方法。
例如,
Integer.class.isInstance(1); //return true
Integer.class.isInstance(null); //return false
编辑:
如果要针对不同的 class 类型进行测试,请编写如下实用方法:
static <T> boolean isInstance(Class<T> type, Object obj) {
return type.isInstance(obj);
}
例如,
Hashing.<String>isInstance(String.class, "hi"); // return true
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.