2
public class Hashing<Key, Elem>

我想检查 Key 是否是 int,所以我将这些行放在构造函数中:

Key key = null;
if (!(key instanceof Integer)) {
    throw new TypeOfKeyStillNotSupportedException();
}

但是,我以这种方式创建了一个:

tHash = new Hashing<Integer, Movie>(max);

并且该死的 TypeOfKeyStillNotSupportedException() 弹出。为什么会发生这种情况,我该如何正确地做到这一点?

提前致谢。

编辑:已经发现问题在于键被分配为空。现在的问题是:如何进行检查?

4

6 回答 6

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, ...);
于 2011-05-04T03:26:54.680 回答
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泛型的完整示例:

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 类的“类型不在界限内”。

Floats 和 Integer 都继承自 Number。因此,您可以“扩展 Number”,然后根据您想在代码中使用它的方式检查“instanceof Integer”或“instanceof Float”。

希望它有所帮助:) 干杯!

于 2011-05-04T03:29:34.093 回答
2

Java 泛型是使用类型擦除实现的:泛型信息在用于类型检查后被编译器丢弃,因此在运行时您的类实际上只是Hashing<Object, Object>. 这就是为什么您不能基于泛型类型进行运行时检查的原因。

您可以Class<Key>向构造函数添加类型参数,调用者必须为用作键的类型传递正确的类对象。例如,在 a 中Hashing<Integer, String>, onlyInteger.class将被接受为该参数的值,您可以将其用于运行时类型检查。但是,将键的类对象作为参数传递的要求使得构造函数调用看起来有点尴尬。

于 2011-05-04T03:35:35.353 回答
0

鉴于您的示例中的以下内容:

public class Hashing<K, E>

这是没有意义的:因为当类KType专门化时,它可以被设置为任何东西。我将名称从Keyto更改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支票的背景信息,我不知道您的意图是什么。

检查with是Type一种代码味道,无论如何都可能是错误的方法。Genericinstanceof

看看这里的java.util.HashMap 实现是如何处理这个问题的。

他们只有两个地方使用,它们都是仅接受且不是类型安全instanceof的遗留方法。Object

于 2011-05-04T03:36:43.453 回答
0

处理这种情况的方法是显式测试 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如果是明确的类或接口, 您将获得完全相同的行为。

(另一方面,如果代码说someObj instanceof Key......由于类型擦除问题,那将是编译错误。)

于 2011-05-04T03:51:30.857 回答
0

你需要一个isInstance方法,它是operator的动态等价物。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
于 2011-05-04T03:56:25.270 回答