繁体   English   中英

Java:检查泛型是否为 int

[英]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检查GenericType是一种代码味道,无论如何都可能是错误的方法。

看这里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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM