Java:检查泛型是否为 int

发布于 2024-11-05 08:56:39 字数 470 浏览 2 评论 0原文

public class Hashing<Key, Elem>

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

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

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

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

然后弹出了该死的 TypeOfKeyStillNotSupportedException() 。为什么会发生这种情况以及我该如何正确地做到这一点?

提前致谢。

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

public class Hashing<Key, Elem>

I want to check if Key is an int, so I place this lines in the constructor:

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

However, I create one this way:

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

And the damn TypeOfKeyStillNotSupportedException() pops. Why is this happening and how can I do it properly?

Thanks in advance.

Edit: Already found that the problem is with key being assigned null. The question is now: How to do the check?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

高冷爸爸 2024-11-12 08:56:40

null 不是任何东西的 instanceof 。由于类型擦除,无法在运行时直接检查 Key 的类型。一种选择是让用户将 Class 传递给构造函数,以便您可以检查:

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, ...);

null is not an instanceof anything. Due to type erasure, there's no way to check the type of Key directly at runtime. One option is to make the user pass in Class<Key> to the constructor so that you can check that:

public Hashing(Class<Key> keyType, ...) {
  if (keyType != Integer.class) {
    throw new TypeOfKeyStillNotSupportedException();
  }
  ...
}

...

Hashing<Integer, Foo> hashing = new Hashing<Integer, Foo>(Integer.class, ...);

To save yourself from having to repeat the type arguments, you can create a static factory method:

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, ...);
柠檬心 2024-11-12 08:56:40

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

您可以将 Class 类型的参数添加到构造函数,调用者必须传递用作键的类型的正确类对象。例如,在 Hashing 中,只有 Integer.class 会被接受作为该参数的值,并且您可以将其用于运行时类型检查。不过,将密钥的类对象作为参数传递的要求使得构造函数调用看起来有点尴尬。

Java generics are implemented using type erasure: the generic information is discarded by the compiler after being used for type checking, so at runtime your class is effectively just Hashing<Object, Object>. That's why you can't do runtime checks based on a generic type.

You can add an argument of type Class<Key> to the constructor, and the caller will have to pass the correct class object for the type being used as the key. For example, in a Hashing<Integer, String>, only Integer.class will be accepted as the value of that argument, and you can use that for runtime type checking. The requirement to pass a the key's class object as a parameter makes the constructor call look a little awkward, though.

左岸枫 2024-11-12 08:56:40

如果您的代码有“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”,具体取决于您希望如何在代码中使用它。

希望它有帮助:) 干杯!

If your code has "key = null;" right before the test of instanceof, then the Exception will necessarily be thrown.

The reason being that the instancof operator checks the reference of the type of object being pointed to and not how it is declared to be.

You can try with this simple example and remove the comments accordingly to see the difference:

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");
}

Also, you can find out more details here:

http://download.oracle.com/javase/tutorial/java/nutsandbolts/op2.html

Hope it helps :)


Full blown example of 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
    }
}

Also note that by having 'Key extends Integer', an exception will be thrown during Runtime if you pass that does not subclass Integer. Furthermore, if you're using and IDE that checks for it, it'll be flag as 'Type not within bound' of the GenTest Class.

Floats and Integer all inherit from Number. Thus you can 'extend Number' and then check for 'instanceof Integer' or 'instanceof Float' depending on how you want to use it in your code.

Hope it helps :) Cheers!

紫轩蝶泪 2024-11-12 08:56:40

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

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();
}

这将是一个更通用的解决方案,但这也没有意义,因为 key始终是一种类型K

key 不能为 null,因为 null 不属于任何 Type

没有对 instanceof 检查周围的内容有更多上下文我不知道您的意图是什么。

使用 instanceof 检查 GenericType 是一种代码味道,而且可能是错误的方法。

看看这里 java.util.HashMap 实现解决了这个问题。

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

Given the following from your example:

public class Hashing<K, E>

This makes no sense: because K is a Type that can be set to anything when the class is specialized. I changed the name from Key to K to remove confusion that you might have that Key isn't representing a Type. The general standard for Type names is to use single characters most of the time.

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

if you change it to

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

that would be a more Generic solution, but that doesn't make sense either because key will always be a type of K

key can't be null because null is not of any Type

Without having more context to what surrounds the instanceof check I don't know what your intention is.

Checking the Type of a Generic with instanceof is a code smell, and probably the wrong approach regardless.

Look here at how the java.util.HashMap implementation handles this problem.

There is only two places where they use instanceof and those are both legacy methods that accept only Object and are not typesafe.

眼波传意 2024-11-12 08:56:40

处理这个问题的方法是显式测试 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 ...,由于类型擦除问题,这将是一个编译错误。)

The way to deal with this is to explicitly test for 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();
}

For the record, those people who responded that this was something to do with type erasure are off base. You would get exactly the same behaviour if Key was a definite class or interface.

(On the other hand, if the code had said someObj instanceof Key ... that would be a compilation error because of the type erasure issue.)

孤凫 2024-11-12 08:56:40

您需要一个 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

You need an isInstance method which is the dynamic equivalent of instanceof operator.

For example,

Integer.class.isInstance(1); //return true
Integer.class.isInstance(null); //return false

Edit:
If you want to test against different class type, write a utility method like this:

static <T> boolean isInstance(Class<T> type, Object obj) {
    return type.isInstance(obj);
}

For example,

Hashing.<String>isInstance(String.class, "hi"); // return true
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文