Java:检查泛型是否为int

时间:2011-05-04 03:22:23

标签: java generics instanceof

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。现在的问题是:如何进行检查?

6 个答案:

答案 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